react笔记基础部分(组件生命周期路由)

注意点:

class是一个关键字, 类。 所以react 写class, 用classname ,会自动编译替换class

点击方法:

 <button onClick = {this.sendData}>给父元素传值</button>

常用的插件:

需要引入才能使用的:

 路由五兄弟
 
import {BrowserRouter as Router, Link, Route, Redirect, Switch} from 'react-router-dom'


react-redux

npm install react-redux --save

初始配置 app页面

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

1.react简介:

简介:React 构建用户界面的javascript库,主要用于构建按ui界面。 instagram,2013年开源。

特点:

  • 声明式的设计
  • 高效,采用虚拟DOM来实现DOM的渲染,最大限度的减少DOM的操作
  • 灵活,跟其他库灵活搭配使用
  • jsx, 俗称给你JS 里面写HTML, JavaSxript 语法的扩展。
  • 组件化,模块化。代码容易复用,大型项目非常喜欢react.(2016年前,vue还没有火之前)
  • 单项数据流/没有实现数据的双向绑定。 数据 --> 视图 --> 事件 --> 数据

2 使用 引入react

2.1 CDN:

只用于本地的学习和使用。 线上形目不能这样啊

可以通过 CDN 获得 React 和 ReactDOM 的 UMD 版本。

<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

2.2 脚手架

cnpm install -g create-React-app

# 全局安装"create-react-app"架构
$ npm install -g create-react-app
 
# 创建脚手架项目
$ create-react-app my-app
 
# 进入项目目录
$ cd my-app
 
# 启动项目
$ npm start

http://localhost:3000/

执行npm start 时, 会自动编译dom,插入到src中的index.html,因为浏览器才不管你用了什么插件,他只会显示解析html正常的dom。

3. npm start 发生了什么 代码原理

入口文件:
1.网页入口文件放在 dist/index.html
2. react入口文件放在 src/index.js

在package.json的script中新增命令
"scripts": {
    "dev": "cross-env NODE=dev"
}



$ npm run build
# 等同于执行
$ node build.js

npm start是npm run start  简写形式

也就是说npm start=  node start.js 执行文件
npm run 查看当前项目的所有的


https://blog.csdn.net/cuipengchong/article/details/73044737?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159479718919724811836533%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=159479718919724811836533&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v3~pc_rank_v3-1-73044737.pc_ecpm_v3_pc_rank_v3&utm_term=npm%E8%84%9A%E6%9C%AC+npm+scripts

npm脚本 npm scripts
概念: npm脚本指的是package.json中的scripts字段
npm允许在package.json文件里面,使用scripts字段定义脚本命令。
就像 node 中执行1.js 可以写成 node 1  一样

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

scripts:{
"build":'node build.js'
}



----------------------分割线--------------------------

https://blog.csdn.net/qq_39956624/article/details/89352115?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159479854019195264540861%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=159479854019195264540861&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v3~pc_rank_v3-1-89352115.pc_ecpm_v3_pc_rank_v3&utm_term=react-scripts+start

在命令窗口输入的是npm start,而start调用的是

 package.json 中的
 
 "start": "react-scripts start",

代码会找到 node_modules里面的react-scripts 插件。查找 bin 文件 点开bin\react-scripts.js文件内容

 .concat(require.resolve('../scripts/' + script))
 从上面这话可以看出调用start时需要调用scripts/start.js,点开该文件:

  1. 打开config/paths.js,发现其实里面好多默认的配置都是写在该文件,可以通过修改改文件来实现自己文件的存放配置
  2. 点开webpack.config.dev.js,也会发现大量是曾相识的代码:
  3. 所以说我们以前通过手动配置的webpack.config.js的内容,react-scripts都已经帮我们做了,大大方便了我们的使用。

----------------------分割线--------------------------

npm的原理

npm 脚本的原理非常简单。每当执行npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。

比较特别的是,npm run新建的这个 Shell,会将当前目录的node_modules/.bin子目录加入PATH变量,执行结束后,再将PATH变量恢复原样。

这意味着,当前目录的node_modules/.bin子目录里面的所有脚本,都可以直接用脚本名调用,而不必加上路径。比如,当前项目的依赖里面有 Mocha,只要直接写mocha test就可以了。

例如

“test”: “mocha test”
1
而不用写成下面这样。

“test”: “./node_modules/.bin/mocha test”

npm传参

向 npm 脚本传入参数,要使用–标明。

“lint”: “jshint **.js”
1
向上面的npm run lint命令传入参数,必须写成下面这样。

$ npm run lint – --reporter checkstyle > checkstyle.xml

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }

里面是一个个键值对,eject对应react-scripts eject,

当我们执行 npm eject的命令是,npm会找到 package.json中的scripts对象中eject对相应值,然后在执行。


react文档结构

myreact 

 
 |--node_modules   项目依赖包
 |-- public       公共开放资源  静态资源
 |     |--favicon.ico 
 |     | --index.html      相当于vue的 id ='app',等待放置编译好的dom
 |     | --logo.png         react图表
 |     | --mainifest.json  chrome扩展文件
 |     | --robots.txt       告诉爬虫,不要爬我的网页。一般没用。
 |
 |-- src
 |     |--App.css
 |     | --APP.js    app组件
 |     | --App.test.js
 |     | --index.css
 |     | --index.js   入口文件
 |     | --logo.svg
 |     | --servceWorker.js
 |     | --setupTests.js
 |
 | --.gittignore    git 忽略配置文件
 | --package.json    包配置信息
 | --package-lock.json  包配置信息版本固定
 | --README.md         文档说明   
 
 
webpack.config.js -  node_modules 



关于import…form…

index.js主文件为例

import '../gen'  // 不支持根目录下的相对引入文件

import './1.js'
// require ('./1.js')  这两种引入方式,都可以打包进去。

自己的静态图片,官方希望你都放在src中,不要访问外边的资源。img js 新建目录存放。


4 react 组件原理

这是一个组件

App.js

function App() {
  return (
      
    <div className="App">
        我是内容
    </div>

  );
}

这是

index.js 引用的页面

import App from './App';  1.引入


ReactDOM.render(  2.  调用一个方法
  // <React.StrictMode>  严格模式
    <App />,
  // </React.StrictMode>,
  document.getElementById('root')
);



测试1:函数式组件渲染

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

// ReactDOM.render(
//     <App />,
//   document.getElementById('root')
// );

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister(); //缓存

页面生成时间,1s刷线一次。
function clock(){
  let time = new Date().toLocaleTimeString();
let element = <div>{time}</div>;
let root =  document.getElementById('root');
ReactDOM.render(element,root);
}

setInterval(clock,1000 )


测试2:组件传参

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

function Clock(props) {
  console.log(props);  //2.props  { data1:4,data2:40 }传入的值,会放到形参中。
  return ( 
    <div > 
     {  props.data1}
      </div>
    )
  }

function run(){

  ReactDOM.render(
  <Clock data1 = { 4} data2 = { 40}/>, //1. 标签首位字母大写

document.getElementById('root')
  );
  
}
  setInterval(run, 1000)


  // let time = new Date().toLocaleTimeString(); 
  //不同点: props

5 Jsx 表达式

优点:

  • JSX执行更快,编辑为JavsScript 代码是进行优化。

  • 类型更安全,编译过程如果出错就不能编译,及时发现错误。

  • JSX编写模板更加简单快速(不要更vue比,当时VUE还没出来)

    注意点:*

    1. jsx必须要有根节点
    2. 正常的普通HTML元素要小写,如果是大写,默认认为是组件。

    jsx表达式:

    1. 有HTML元素构成
    2. 中间使用变量 用 { }
    3. {} 中可以使用表达式 可以使用 jsx对象,
    4. 属性和html内容一样都是用{} 来插入内容。
    5. {} 一个只能放一个表达式 但可以放入嵌套数据结构

{ }

1.里放置表达式
案例1var msg = '姓名';
var time = '00:00'

var dom = (
         <div>
                <div> {msg + time}</div>
        </div>
 )

ReactDOM.render(
  dom,
  document.getElementById('root')
 )




2.案例2 :三元运算法

{ } 里面可以放标签和单元判断

var msg = '发烧';
var dom = (
         <div>
              <div> {msg == '发烧'?  <button>隔离</button> :'没事啊'}</div>
        </div>
 )

ReactDOM.render(
  dom,
  document.getElementById('root')
 )




3. 混搭

{插值中放入标签,三元判断等}

var element4 = '我是混搭';
or

var element4 =
    <div>
          <span> 我是模板混搭 <sapn/> 
     </div>


<div> {msg == '发烧'?  <button>隔离</button> :element4}</div>
   
  dom变成了什么:     
element4:  dom,在这里已经变成了 一个对象。有属性和  _proto_       
       

4 引入css

App.css

.lyx{
  color: red;
}

import引入 css 文件

比如当前页 index.js

直接引入
import './App.css';

注意点: 
<div> {msg == '发烧'?  <div className='lyx'>隔离</div> :'没事啊'}</div>
加clsss  写法注意 className,
测试: 直接写 calss='lyx' 也可以。但是浏览器里会提示错误。


变量js方式 css
let  styledemo = {
  background:"skyblue",
  borderBottom:"4px solid red",  //需要驼峰
    "fontsize":'40px'    //要么加引号,不用驼峰
}

let element = (
<div>
  <h1 style = { styledemo} >我是 react style 的jsx变量写法</h1>
</div>
)


ReactDOM.render(
  element,
  document.getElementById('root')
 )

* 不能写行内样式,报错

添加 自定义 class

let classstr = 'redbg'

let element = (
<div>
  <h1 style = { styledemo} className = {'abc '+ classstr}>我是 react style 的jsx变量写法</h1>
</div>
)

变量类名 和自定义类名, abc 字符串类型,记得一定留出空格。否则编译出来会合并
className = {'abc '+ classstr} 



1. 同时添加多个class

jsx标签中,不能加多个class, 需要处理一下,把class合并在写入。

let classstr = ["redbg","redbg2"].join(" ") //合并字符串当成一个变量放入插值中

let element = (
<div>
  <h1 style = { styledemo} className = {classstr}>我是 react style 的jsx变量写法</h1>
</div>
)

5. jsx中加注释

let element = (
<div>
  {/* jsx的注释写法*/}
  <h1 style = { styledemo} className = {classstr}>我是 react style </h1>
</div>
)

6. 组件的两种方式

6.1编程式 函数里(静态组件)

function Childdom(){
  let title = <h2> 我是副标题</h2>
  let weather = '下雨'
//条件判断
 let isgo = weather === '下雨' ? "下雨不出门" : "不下雨了,不出门" 
  return(
  <div>  
    {title} 
    <span>
      天气怎么样:
      {isgo}
    </span>
    
  </div>
  )}

ReactDOM.render(
  <Childdom/>,
  document.getElementById('root')
 )



另一种传值形式,也是编程式 (组件传值)

function Childdom(props){
  let title = <h2> 我是副标题</h2>
console.log(props);  // props接受传值
  return(
  <div>  
        {title} 
            <span>
              天气怎么样:
                  {props.weather}    // 使用传值
            </span>
    
  </div>
  )}
   
ReactDOM.render(
  <Childdom weather = '来自组件标签'/>,   //标签传值

  document.getElementById('root')
 )

6.2 类组件 class声明(动态组件)

index.js

class HelloWorld extends React.Component{
 render() {                //render这个名字不能动。不是随意取得。是一个规定的方法
      return(
        <div>  
        我是类组件定义
        </div>
      )
 }
}


ReactDOM.render(
  <HelloWorld/>,
  document.getElementById('root')
 )




组件

类组件传参-见序号8

  class Ant extends React.Component {
    constructor(props) {
      super(props)
    this.state = {}
    }
  
    render() {

      return ( 
        <div > 
          
        </div>
      )
    }

    onChange(page,pagesize){
     
    }
  }


export default Ant



6.3组件嵌套(复合组件)

class Children extends React.Component{
  render() {               
       return(
         <div>  
     <div> 我是Children</div>


         </div>
       )
  }
 }

  class HelloWorld extends React.Component{
    render() {              
         return(
           <div>  
       <div> 我是HelloWorld</div>
          <Children/>    //helloworld组件中,引入children组件
           </div>
         )
    }
   }
   
   ReactDOM.render(
     <HelloWorld  weather = '出太阳'/>,
     document.getElementById('root')
    )

结论:两种组件适用场景

函数式: 如果静态,或者就 传一个值,使用函数式

类组件:有触发事件,交互和操作

7. 关键方法:ReactDOM.rende

ReactDOM.render(组件, 挂载点root)


组件这一块,样式可以多种。

第一种 : function ( ) 函数形式

function Childdom(){
  let title = <h2> 我是副标题</h2>
  let weather = '下雨'
//条件判断
 let isgo = weather === '下雨' ? "下雨不出门" : "不下雨了,不出门" 
  return(
  <div>  
    {title} 
    <span>
      天气怎么样:
      {isgo}
    </span>
    
  </div>
  )}

ReactDOM.render(
  <Childdom/>,
  document.getElementById('root')
 )


第二种 : dom形式

其实实质一样,和return() 函数式一样。

let element = (
<div>
  <h1 style = { styledemo} >我是 react style 的jsx变量写法</h1>
</div>
)


ReactDOM.render(
  element,
  document.getElementById('root')
 )

8 传值

function Childdom(props){
  let title = <h2> 我是副标题</h2>
console.log(props);  // props接受传值
  return(
  <div>  
        {title} 
            <span>
              天气怎么样:
                  {props.weather}    // 使用传值
            </span>
    
  </div>
  )}
   
ReactDOM.render(
  <Childdom weather = '来自组件标签'/>,   //标签传值

  document.getElementById('root')
 )

8 传值(类组件传参)

8.1 自己的标签 ——> 传向自己的组件

class Children extends React.Component{
  render() {     
    console.log(this);   //这里的this指的是Children组件 this里propos里有标签传值
       return(
         <div>  
     <div> 我是Children</div>


         </div>
       )
  }
 }

  class HelloWorld extends React.Component{
    render() {       
      console.log(this);   //这里的this指的是HelloWorld组件 this里propos里有标签传值
         return(
           <div>  
       <div> 我是HelloWorld</div>
          <Children name = '我是children的数据' />   
           </div>
         )
    }
   }
   
   ReactDOM.render(
     <HelloWorld  weather = '我是父组件穿的值'/>,
     document.getElementById('root')
    )

8.2 父组件 标签的数据–> 子组件 传递

class Children extends React.Component{
  render() {     
    // console.log(this);   //这里的this指的是Children组件 this里propos里有标签传值
       return(
         <div>  
     <div> 我是Children</div>


         </div>
       )
  }
 }

  class HelloWorld extends React.Component{
    render() {       
      console.log(this);   //这里的this指的是HelloWorld组件 this里propos里有标签传值
         return(
           <div>  
       <div> 我是HelloWorld</div>
          <Children name = '我是children的数据' weather = {this.props.weather}/>   
           </div>
         )
    }
   }
   
   ReactDOM.render(
     <HelloWorld  weather = '我是父组件穿的值'/>,
     document.getElementById('root')
    )

9 react状态 管理(修改数据)

9.1 引入例子

class Clock extends React.Component {
  constructor(props) {
    super(props)
  this.state = {
    time: new Date().toLocaleTimeString()
    }}

  render() {
 // console.log(1);  变了
    return ( 
      <div >
    <h1> 当前时间: {this.state.time}</h1>
      </div>
    )
  }
}

setInterval(()=>{
  // console.log(0);  变了
ReactDOM.render(
  <Clock/> ,
  document.getElementById('root')
);

},1000)

计时器1s渲染一次,我们发现页面没动。手动刷新才会变。
通过打印我们发现,render, 计时器都在变,就是页面不变。
原因是: render方法 每隔1s渲染, <Clock/> 直接加载缓存。所以没变。

既然render变了,那就直接修改state.time的值。

 做如下修改
render() {
  // console.log(0);
              this.state.time = new Date().toLocaleTimeString()
    return ( 
      <div >
                 <h1> 当前时间: {this.state.time}</h1>
      </div>
    )
  }
  
  保存后,页面动了。 

但是这不是官方推荐的方法。

9.2 正确修改方法 setState( )

class Clock extends React.Component {
    平级1
  constructor(props) {
    super(props)
      this.state = {
    time: new Date().toLocaleTimeString()
    }}
  平级2
  render() {
    return ( 
      <div >
                 <h1> 当前时间: {this.state.time}</h1>
      </div>
    )
  }
    平级3
   componentDidMount(){   componentDidMount是声明周期函数,加载完页面开始执行。
    setInterval(() => {
      
      this.setState({
        time : new Date().toLocaleTimeString()
      })
    }, 1000);
   }
}

渲染函数
ReactDOM.render(
  <Clock/> ,
  document.getElementById('root')
);


1.采用官方方法的作用: 修改数据,并自动渲染页面;
2. setstate方法,修改数据后,不会立即更改dom,而是等函数执行完了以后,统一对比虚拟dom,再做修改,提升性能。 小程序也是借鉴这样。

总结: react 类组件中,自己的state数据,和点击事件,和渲染dom,都放到自己的内部,this下挂载。

9.3 案例:

实现两个按钮接环内容
import React from 'react';
import ReactDOM from 'react-dom';

class Clock extends React.Component {
  constructor(props) {
    super(props)
  this.state = {
    c1:"content active",
    c2:"content "

    }
    this.clickEvent = this.clickEvent.bind(this)// 把方法挂载到this组件下

  }

      clickEvent(e){
        console.log(this);
          // console.log(e.target.dataset);
          // console.log(e.target.dataset.index);

         let index = e.target.dataset.index
         if(index == '1'){
           this.setState({
            c1:"content active",
            c2:"content "
           })
         }else{
          this.setState({
            c1:"content ",
            c2:"content  active"
           })
         }
      }

  render() {
    return ( 
      <div >
             <button data-index = '1' onClick = {this. clickEvent }>内容一</button>  
             <button data-index = '2' onClick = {this. clickEvent }>内容二</button>  
            
             <div className = {this.state.c1}>
                          <h1>内容一</h1>   
             </div>
             <div className = {this.state.c2}>
                          <h1>内容二</h1>   
             </div>

      </div>
    )
  }
  
}

ReactDOM.render(
  <Clock/> ,
  document.getElementById('root')
);

案例里:用到了几个点
e 事件对象
DOM data自定义属性和使用
bing(this) 改变this指向


10 传值

10.1 父传子

父传子数据,单向流动,不能子传父。 props的传值,可以是任意的类型。

props可以设置默认值。

HelloMessage.dafaultProps = { name:‘tom’ ,msg:‘hellowlorld’ }

注意:prop可以传递函数,可以传递父元素的函数。也就是说,可以修改父元素的state数据,从而道道传递 数据 的效果和目的。

import React from 'react';
import ReactDOM from 'react-dom';

class Clock extends React.Component {
  constructor(props) {
    super(props)
  this.state = {
    isshow:true

    }
      this.changeshow = this.changeshow.bind(this)
  }

  changeshow(){
    this.setState({
      isshow:!this.state.isshow
    })
    
         }


  render() {
    return ( 
      <div >
        <button onClick = {this.changeshow}>控制子元素显示</button>
            <Children  isactive = {this.state.isshow}/>

      </div>
    )
  }
  
}

class Children extends React.Component {
  constructor(props) {
    super(props)
  this.state = {
    }

  }

      render() {
        let strclass = null;

        if(this.props.isactive){
          
          strclass = 'active'
        }else{
      
          strclass = ""
        }

    return ( 
      <div >
        <span className = {'content '+ strclass}>i is children</span>
      </div>
    )
  }
  
}

ReactDOM.render(
  <Clock/> ,
  document.getElementById('root')
);

总结: 父元素states准备一个变量,在自己函数内,子组件标签,输入值, 子组件接受props接受使用。

10 2 子传父

方法: 调用父元素的函数,从而操作元素的数据。

import React from 'react';
import ReactDOM from 'react-dom';




class Clock extends React.Component {
  constructor(props) {
    super(props)
   this.state = {
    childData:null  //默认是null页面不会显示,只有 有数据才会显示
   }
    
  }


  render() {
    return ( 
      <div >
      <h1>子元素传递给复原的数据 {this.state.childData} </h1>
      <Children setChildDate = {this.setChildDate} />       //1. 变量也可以是个方法

      </div>
    )
  }
  setChildDate = (a)=>{  //3.传递形参,进行修改
    this.setState({
      childData:a
    })
  }
}

class Children extends React.Component {
  constructor(props) {
    super(props)
  this.state = {
    msg:'helloworld'
    }
  }

  sendData = ()=>{
      this.props.setChildDate(this.state.msg) // 2. 你要记住,标签传参,实例中props中就会有值。
  }
      render() {
        return ( 
          <div >
            <button onClick = {this.sendData}>给父元素传值</button>
          </div>
        )
  }
}
  ReactDOM.render(
    <Clock/> ,
    document.getElementById('root')
  );

简写形式: 既然children标签传入, children的props中就会挂载。那么就可以这样写:
 <button onClick = {()=> {this.props.setChildDate('我是子组件调用props')}}>给父元素传值</button> ,这样也是可以调用的。   匿名的箭头函数,this.不变。


11 reach 事件语法

特点:
  1. 事件的 click 写法,驼峰命名法。2. { } 传入一个函数,而不是一个字符串.
<button onClick = {this.sendData}>给父元素传值</button>

处理过的事件对象e 和 阻止默认
import React from 'react';
import ReactDOM from 'react-dom';


class Clock extends React.Component {
  constructor(props) {
    super(props)
   this.state = {
 
   }
  }
  render() {
    return ( 
      <div >
   <div onClick = { this.parentEvent } data-index = 'lyx'>
     查看事件对象e
   </div>
      </div>
    )
  }
  parentEvent = (e)=>{
    console.log( e) //注意:这个事件都想是react 处理过的。如果想拿到具体值,直接输出 e.target.dataset.index
  }
}
  ReactDOM.render(
    <Clock/> ,
    document.getElementById('root')
  );


阻止默认

  组件: 
form 有默认提交事件,同步的。如果想自定义ajax异步请求,就阻止默认。
render() {
    return ( 
      <div >
             <form action="https://www.baidu.com" method="get">
                     <button onClick = {this.parentEvent}>提交</button>
           </form>
      </div>
    )
  }
  
  
  方法1parentEvent = (e)=>{
    console.log(e ) //注意:想知道e中有什么方法,打印出来一个一个查一下。 
    e.preventDefault()
  }
  方法2
  form中的提交按钮,submit修改为button , 不设置默认submit.
  <button onClick = {this.parentEvent} type = 'submit'>提交</button>

传参,同时保留事件对象
  render() {
    return ( 
      <div >
           <form action="https://www.baidu.com" method="get">
          <button onClick = {(e)=>{this.parentEvent(e, "0")}} type = 'button'>提交</button>
           </form>
      </div>
    )
  }
  parentEvent = (e,a)=>{
    console.log(e ,a) //注意:想知道e中有什么方法,打印出来一个一个查一下。 
    // e.preventDefault()
  }

注意:
<button onClick = {()=>{this.parentEvent("0")}} type = 'button'>提交

这样的话,传值,会把e替换。

不适用箭头函数传递多个参数

箭头函数与function函数的区别,就是this. 所以bind,修改一下this.指向。

function, 内部的this,就是它自己,谁调用,指向谁。

使用箭头函数
<button onClick = {()=>{this.parentEvent("0")}} type = 'button'>提交</button>
不适用箭头函数
 <button onClick = {function(e){this.parentEvent('msg:helloworld',e)}.bind(this)} type = 'button'>提交</button>


 parentEvent = (e,a)=>{
    console.log(e ,a)  //形参,按位置传递 
  
  }

12 条件渲染

React 中条件渲染即和JavaScript 中,条件运算,如if else 三元运算符等等。

1 直接通过条件渲染你返回要渲染的jsx对象。

2 通过条件运算得出jsx对象,在将jsx对象渲染到模板中。

第一种
import React from 'react';
import ReactDOM from 'react-dom';

function User(props){
  return ( <h1>我登陆了</h1>)
}

function UserNologin(props){
  return ( <h1>请登录</h1>)
}

class Clock extends React.Component {
  constructor(props) {
    super(props)
   this.state = {
      islogin:false
   }
  }
  render() {
    if(this.state.islogin){
      return(<User></User>)
    }else{
      return(<UserNologin></UserNologin>)
    }
  }
}

  ReactDOM.render(
    <Clock/> ,
    document.getElementById('root')
  );
通过控制islogin, 达到页面变化。


第二种
import React from 'react';
import ReactDOM from 'react-dom';



function User(props){
  return ( <h1>我登陆了</h1>)
}

function UserNologin(props){
  return ( <h1>请登录</h1>)
}

class Clock extends React.Component {
  constructor(props) {
    super(props)
   this.state = {
      islogin:false
   }
  }
  render() {
    let element = null

    if(this.state.islogin){
      element =( <User></User> )
    }else{
      element =  (<UserNologin></UserNologin>)
    }

      return(  
        <div> 
          <div>这是头部</div>
            {element}
        <div>这是尾部</div>
        </div>
      )
  }
}



  ReactDOM.render(
    <Clock/> ,
    document.getElementById('root')
  );

//可以发现, react 就是你想要什么样的逻辑,自己动手。

第三种: 三元运算符形式
render() {
   
      return(  
        <div> 
          <div>这是头部</div>
            {this.state.islogin ?( <User></User> ):  (<UserNologin></UserNologin>)}
        <div>这是尾部</div>
        </div>
      )
  }

13 列表渲染

将列表内容拼装成数组放置到模板中。

将数据封装成数组的JSX对象。

import React from 'react';
import ReactDOM from 'react-dom';



let arr = ['小明','小黑','小白']

class Clock extends React.Component {
  constructor(props) {
    super(props)
   this.state = {
      islogin:true
   }
  }
          render() {
              return(  
                <div> 
                    <ul>
                          {arr}
                    </ul>
                </div>
              )
          }
}

  ReactDOM.render(
    <Clock/> ,
    document.getElementById('root')
  );


渲染结果:
<ul>
  小明
小黑
小白
</ul>

改造:

let arr = ['小明','小黑','小白']

我们设置一个jsx数组

let arrhtml = [<li>小明</li>,<li>小黑</li>,<li>小白</li>]

               
  render() {
              return(  
                <div> 
                    <ul>
                          {arrhtml}
                    </ul>
                </div>
              )
          }
        
渲染结果: 完美
<ul><li>小明</li><li>小黑</li><li>小白</li></ul>
      

列表循环jsx。

import React from 'react';
import ReactDOM from 'react-dom';


class Clock extends React.Component {
  constructor(props) {
    super(props)
   this.state = {
     listarr : [
       {
          title:'第一个标题1',
          cont:'我是内容1'
       },
       {
          title:'第一个标题2',
          cont:'我是内容2'
       }
     ]
   }
  }
          render() {
            let listArr = []
            console.log(0);
            for(let i = 0 ;i < this.state.listarr.length;i++){
      
              var  item =  (
                <li>
                  <h3>{this.state.listarr[i].title}</h3>
                   <p>{this.state.listarr[i].cont}</p>
                </li>
              )
              listArr.push(item) 
            }
      
              return(  
                <div> 
                    <ul>
                          {listArr}
                    </ul>
                </div>
              )
          }
}



  ReactDOM.render(
    <Clock/> ,
    document.getElementById('root')
  );


代码简化 map循环

使用数组的map方法,对每一项数据按照JSX的形式加工,最终得到,每一项都是JSX对象的数组,在将数组渲染到模板中去。

  render() {
            let listArr = this.state.listarr.map((itme,index)=>{
              return(
             <div key = {index} className = {'item'+index}>
                    <li>{itme.title}</li>
                    <p>{itme.cont}</p>
             </div>
            
              )
            })
              return(  
                <div> 
                    <ul>
                          {listArr}
                    </ul>
                </div>
              )
          }

14 肺炎列表渲染案例

总结: render里面可以写js逻辑,完全就是原生js写的。

这个暂用:

import React from 'react';
import ReactDOM from 'react-dom';

var data = require('./1.json')
console.log(data);

class Clock extends React.Component {
  constructor(props) {
    super(props)
   this.state = {
     listarr : [
       {
          title:'第一个标题1',
          cont:'我是内容1'
       },
       {
          title:'第一个标题2',
          cont:'我是内容2'
       }
     ]
   }
  }
          render() {
            let listArr = this.state.listarr.map((itme,index)=>{
              return(
             <div key = {index} className = {'item'+index}>
                    <li>{itme.title}</li>
                    <p>{itme.cont}</p>
             </div>
            
              )
            })
            
              return(  
                <div> 
                    <ul>
                          {listArr}
                    </ul>
                </div>
              )
          }
}



  ReactDOM.render(
    <Clock/> ,
    document.getElementById('root')
  );


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

15 生命周期函数

https://blog.csdn.net/qq_38719039/article/details/82378434

img

生命周期: 针对组件总渲染到销毁的过程。期间有可以调用的函数,又叫钩子函数

生命周期的3个状态。

Mounting: 将组件插入到dom中。

Updating: 将数据更新到dom中。

Unmounting: 将组件移除Dom中。

生命周期中的钩子函数(方法,事件)

componentWillMount: 组件将要渲染 -> AJAX,添加动画前的类

componentDidMount : 组件渲染完毕 -> 添加动画 添加echart 就在这里 获取windown

compontWillReceiveProps:组件将要接受props数据 ->查看props的数据是什么

componentWillReceiveProps: 组件接收到新的state或者props ->判断是否更新。 返回布尔值。

CompontWillUpdate : 组件将要更新

componentDidUpdate :组件已经更新

componentWillUnmount : 组件 将要卸载

// 已经更正

1.constructor(props, context)

  • 构造函数,在创建组件的时候调用一次。

2.componentWillMount()

  • 在组件render之前立即调用

Tip1: 不建议在此请求数据,由于请求数据接口一般都是异步,这时候render已经被执行,建议在componentDidMount 数据

Tip2: 如果在服务端渲染,该钩子函数将被调用两次,一次服务端,一次浏览器端,而componentDidMount函数只会在浏览器端请求一次

Tip3: 在taro构建的小程序里对应的生命周期是 onLoad。

3…componentDidMount()

  • 所有的组件(包括子组件)在render执行完之后立即调用,并且只会被调用一次。

Tip: 建议在此请求数据

4. componentWillReceiveProps(nextProps)

  • 在props被改变时被触发,初始化render时不调用。
  • 旧的属性还是可以通过this.props来获取,在这里通过调用this.setState()来更新你的组件状态。

Tip1: 某些情况下,props没变也会触发该钩子函数,需要在方法里手动判断一下this.props和nextProps是否相同,不相同了才执行我的更新方法。

Tip2:该函数一般用来更新依赖props的状态

5. shouldComponentUpdate(nextProps, nextState)

  • 发生重渲染时,在render()函数调用前被调用的函数,当函数返回false时候,阻止接下来的render()函数的调用,阻止组件重渲染,而返回true时,组件照常重渲染。
  • 该方法并不会在初始化渲染或当使用forceUpdate()时被调用。

6.componentWillUpdate(nextProps, nextState)

  • shouldComponentUpdate返回true或者调用forceUpdate之后,componentWillUpdate会被调用。

7. getSnapshotBeforeUpdate(prevProps, prevState)

  • 该函数在最新的渲染输出提交给DOM前将会立即调用。它让你的组件能在当前的值可能要改变前获得它们。这一生命周期返回的任何值将会 作为参数被传递给componentDidUpdate()。

8. componentDidUpdate(prevProps, prevState)

  • 除了首次render之后调用componentDidMount,其它render结束之后都是调用componentDidUpdate。

9.componentWillUnmount()

  • 在组件被卸载和销毁之前立刻调用。可以在该方法里处理任何必要的清理工作,例如解绑定时器,取消网络请求,清理任何在componentDidMount环节创建的DOM元素。

10.componentDidCatch(error, info)

  • 该函数称为错误边界,捕捉发生在子组件树中任意地方的JavaScript错误,打印错误日志,并且显示回退的用户界面。

Tip:错误边界只捕捉树中发生在它们之下组件里的错误。一个错误边界并不能捕捉它自己内部的错误。

11.render()

  • render是一个React组件所必不可少的核心函数(上面的其它函数都不是必须的)。

Tip:记住,不要在render里面修改state。

12.React组件更新路径

在线测试:http://wximg.gtimg.com/shake_tv/test/lifeCycle2113.html

钩子函数位置 ( 完整code)

import React from 'react';
import ReactDOM from 'react-dom';



class Clock extends React.Component {
  constructor(props) {
    super(props)
      this.state = {
        msg:'hello world'
      }
  }


// componentWillMount   组件将要渲染
componentWillMount(){
  console.log(' CompontWillMount: 组件将要渲染')
}

// CompontDidMount: 组件渲染完毕
CompontDidMount(){
  console.log(' CompontDidMount: 组件渲染完毕')
}
// compontWillReceiveProps:组件将要接受props数据
compontWillReceiveProps(){
  console.log(' compontWillReceiveProps:组件将要接受props数据')
}
// componentWillReceiveProps : 组件接收到新的state或者props,判断是否更新。 返回布尔值。
componentWillReceiveProps(){
  console.log(' componentWillReceiveProps: 组件接收到新的state或者props')
}

// CompontWillUpdate: 组件将要更新
CompontWillUpdate(){
  console.log(' CompontWillUpdate: 组件将要更新')
}

// componentDidUpdate组件已经更新

componentDidUpdate(){
  console.log(' ComponentDidUpdate:组件已经更新')
}

// componentWillUnmount : 组件 将要卸载

componentWillUnmount(){
  console.log(' componentWillUnmount : 组件 将要卸载')
}

          render(){

              return(  
                <div> 
                  
                </div>
              )
          }
}



  ReactDOM.render(
    <Clock/>,
    document.getElementById('root')
  );

总结: 钩子函数在构造函数内,

测试:使用上面的code, 测试,页面打开的时候:显示 CompontWillMount:组件将要渲染

点击修改数据的时候: ComponentDidUpdate:组件已经更新。 其他的等待测试。


补充: 组件的成员和他们的this

import React from 'react';
import ReactDOM from 'react-dom';



class Clock extends React.Component {

// ----------------------分割线----------------------------------------------
  constructor(props) {
    super(props)
      this.state = {
        msg:'hello world'
      }
      console.log(this);// this指向实例
      this.clickEvent = this.clickEvent.bind(this)// 把方法挂载到this组件下
  }


// ----------------------分割线----------------------------------------------

          render(){
            console.log(this); // this指向实例
              return(  
                <div> 
                  {/* <button onClick = {this.clickEvent}>点击修改数据</button> */}
                  <button onClick = {this.clickEvent.bind(this)}>点击修改数据</button>
                  <span>{this.state.msg}</span>
                </div>)}

// ----------------------分割线----------------------------------------------
            clickEvent(e){
//没有bing,this= undefind ;加上bing现在this已经指向实例.才能使用实例上的方法。this.setstate
           console.log(this); 
              // this.setState({
              //   msg:'修改内容'
              // })
            }
// ----------------------分割线----------------------------------------------

} // 组件的下括号

//  上图表明: 组建中三个部分: constructor   render   dom的clickEvent  三个是并列。
// 正由于是并列的,所以this不统一。  
//  所以只要保证this是统一实例。 button可以这两中写法。看上图

  ReactDOM.render(
    <Clock/>,
    document.getElementById('root')
  );

案例: 疫情 中国地图 引入echart

npm install echarts

import React from 'react';
import ReactDOM from 'react-dom'; //

var echarts = require('echarts');//该中引入方式默认实在node_modules 中 npm安装



class Clock extends React.Component {
// -----------------分割线---------------------------
  constructor(props) {
    super(props)
      this.state = {
        msg:'hello world',
        my_series_data:[5, 20, 36, 10],
        my_xAxis_data:["衬衫", "羊毛衫", "雪纺衫", "没有裤子"]
      }
  }
// -----------------分割线---------------------------
      componentDidMount() {
        console.log(this); //指向实例
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));
        // 绘制图表
        let shuju ={
          title: { text: 'ECharts 入门示例' },
          tooltip: {},
          xAxis: {
              data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
          },
          yAxis: {},
          series: [{
              name: '销量',
              type: 'bar',
              data: [5, 20, 36, 10, 10, 20]
          }]
      }
          //  拦截原始数据,用自己的数据替换一下
          console.log(shuju);
           shuju.series[0].data = this.state.my_series_data
           shuju.xAxis.data = this.state.my_xAxis_data

        myChart.setOption(shuju);  //渲染图表

    }
// -----------------分割线---------------------------
          render(){
              return(  
                <div className="myecahrt"> 
                        <h1>我的creact 图表</h1>
                        <div id="main" style={{ width: 400, height: 400 }}></div>
                </div>)
                }
// -----------------分割线---------------------------
} 


  ReactDOM.render(
    <Clock/>,
    document.getElementById('root')
  );

  // 总结: npm 引入 js  ;data中准备好自己的数据; render中准备好挂载点,
  // ;钩子函数,组件dom渲染上后,寻找dom,初始化echart方法,在渲染前替换自己的的数据。
 


引入echar map地图

import React from 'react';
import ReactDOM from 'react-dom'; 


import echarts from 'echarts'

import 'echarts/map/js/china';

  // require ('echarts/map/js/china')


// import ('echarts/map/js/china');  采用该种方法引入 报错 如下:
// Expected an assignment or function call and instead 
// saw an expression  no-unused-expressions

 class App extends React.Component {
  // export class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
        
            data:[
                {
                    name: "南海诸岛",
                    value: 0
                },
                {
                    name: '北京',
                    value: 20
                },
                {
                    name: '天津',
                    value: 30
                },
                {
                    name: '上海',
                    value: 229
                },
                {
                    name: '重庆',
                    value: 59
                },
                {
                    name: '河北',
                    value: 190
                },
                {
                    name: '河南',
                    value: 300
                },
                {
                    name: '云南',
                    value: 20
                },
                {
                    name: '辽宁',
                    value: 40
                },
                {
                    name: '黑龙江',
                    value: 37
                },
                {
                    name: '湖南',
                    value: 180
                },
                {
                    name: '安徽',
                    value: 0
                },
                {
                    name: '山东',
                    value: 67
                },
                {
                    name: '新疆',
                    value: 10
                },
                {
                    name: '江苏',
                    value: 0
                },
                {
                    name: '浙江',
                    value: 0
                },
                {
                    name: '江西',
                    value: 0
                },
                {
                    name: '湖北',
                    value: 0
                },
                {
                    name: '广西',
                    value: 0
                },
                {
                    name: '甘肃',
                    value: 0
                },
                {
                    name: '山西',
                    value: 0
                },
                {
                    name: '内蒙古',
                    value: 89
                },
                {
                    name: '陕西',
                    value: 0
                },
                {
                    name: '吉林',
                    value: 0
                },
                {
                    name: '福建',
                    value: 66
                },
                {
                    name: '贵州',
                    value: 0
                },
                {
                    name: '广东',
                    value: 330
                },
                {
                    name: '青海',
                    value: 0
                },
                {
                    name: '西藏',
                    value: 74
                },
                {
                    name: '四川',
                    value: 601
                },
                {
                    name: '宁夏',
                    value: 0
                },
                {
                    name: '海南',
                    value: 45
                },
                {
                    name: '台湾',
                    value: 23
                },
                {
                    name: '香港',
                    value: 0
                },
                {
                    name: '澳门',
                    value: 0
                }
            ]
       

        }
    }

    componentDidMount(){
        this.initMap();
    }
    
    //初始化地图

    initMap = () => {
        let myChart = echarts.init(document.getElementById('myMap'));
        let option = {
            tooltip: {
                formatter: function (e , t, n) {
                    return e.seriesName + "<br />" + e.name + ":" + e.value
                }
            },
            visualMap: {
                min: 0,
                max: 1000,
                right: 26,
                bottom: 40,
                showLabel: !0,
                pieces: [{
                    gt: 500,
                    label: "500家以上",
                    color: "#ED5351"
                }, {
                    gte: 200,
                    lte: 500,
                    label: "201-500家",
                    color: "#3B5A97"
                }, {
                    gte: 100,
                    lt: 200,
                    label: "101-200家",
                    color: "#59D9A5"
                }, {
                    gt: 51,
                    lte: 100,
                    label: "51-100家",
                    color: "#F6C021"
                }, {
                    label: "1-50家",
                    gt: 0,
                    lte: 50,
                    color: "#6DCAEC"
                }
                ],
                show: !0
            },
            geo: {
                map: "china",
                roam: !1,
                scaleLimit: {
                    min: 1,
                    max: 2
                },
                zoom: 1.13,
                layoutCenter: ['30%', '30%'],                //地图中心在屏幕中的位置
                label: {
                    normal: {
                        show: !0,
                        fontSize: "14",
                        color: "rgba(0,0,0,0.7)"
                    }
                },
                itemStyle: {
                    normal: {
                        borderColor: "rgba(0, 0, 0, 0.2)"
                    },
                    emphasis: {
                        areaColor: "#F5DEB3",
                        shadowOffsetX: 0,
                        shadowOffsetY: 0,
                        borderWidth: 0
                    }
                }
            },
            series: [{
                name: "客户统计",
                type: "map",
                geoIndex: 0,
                data: this.state.data,
                areaColor: '#0FB8F0'
            }]
        };
        myChart.setOption(option);
        window.addEventListener("resize", function () {
            myChart.resize();
        });
    }
  
      render(){
        return (
            <div className="map">
                <div id="myMap" style = {{"height":"800px"}} ></div>
            </div>
        )
    }
}



    ReactDOM.render(
      <App/>,
      document.getElementById('root')
    );




16 表单和图表 seach案例

涉及点: 父子传值, 常规dom渲染理解为jsx对象,map循环,

子页面的绑定事件,模块导出。

index.js

import React from 'react';
import ReactDOM from 'react-dom';


import Search from './component/search';

class Clock extends React.Component {

  constructor(props) {
    super(props)
   this.state = {
     listarr : [
       {
         id:1,
          title:'第一个标题1',
          cont:'我是内容1'
       },
       {
        id:2,
          title:'第一个标题2',
          cont:'我是内容2'
       }
     ]
   }
  }
          render() {
            let listArr = this.state.listarr.map((itme,index)=>{
              return(
             <div key = {index} className = {'item'+index}>
                    <li>{itme.title}</li>
                    <p>{itme.cont}</p>
             </div>
            
              )
            })
            
         

              return(  
          
                <div> 
                  <Search alldata = {this.state.listarr}></Search>
                    <ul>
                          {listArr}
                    </ul>
                </div>
              )}
}

  ReactDOM.render(
    <Clock/> ,
    document.getElementById('root')
  );

search.js页面

import React from 'react';

class Search extends React.Component {

    constructor(props) {
      super(props)
     this.state = {
        value:undefined,
        result:":查询结果"
     }
    }
                render() {
                    return(   
                        <div className= 'search'> 
                              <input type="text" onKeyDown = {this.serchEvent.bind(this)}  placeholder='请输入' 
                            //   value = {this.state.value}
                            //   onChange = {this.chengeEvent.bind(this)}

                              />
                                    <div>
                                        <h2>查询结果</h2>
                                        <div>
                                            这是查询结果 search
                                            {this.state.result}
                                        </div>
                                    </div>
                         
                        </div>
                    )}

      serchEvent(e){
            // let a = this.props.alldata[e.target.value]
            if(e.keyCode === 13){
 
                if(this.props.alldata[e.target.value]){
                    this.setState({
                        result :(<h2>{this.props.alldata[e.target.value].cont}</h2> )
                    })
                }else{
                    this.setState({
                            result :(<h2>只有两条数据啊</h2> )
                  
                    })
                }  
            }
      }

      chengeEvent(e){

// console.log(e.target.value);
            this.setState({
                // value:e.target.value
            })
      }
    }
    
    export default Search;

17 React 的ajax案例

Ajax + React + axios + Express 案例

17-1 服务端

环境准备

常规准备
1. npm init    生成package.son文件 记录以来信息
2. npm i webpack --save-dev   安装webpack  生成node_modules 打包依赖文件  18M大小
项目使用的插件和框架准备

3.npm install express --save      --save是保存版本信息。其中主要封装的是http。   
4.  npm install --global  n         odemon热加载



新建index.js

// 0 安装 
// 1 引包
const express = require('express')  // 引包

const app = express() //调用
// app.get('/', (req, res) => res.send('Hello World!'))  //res.send 这里 变了

app.get('/', function(req, res){
        res.send('Hello World!')
})

  // 再写一个
app.get('/app', function(req, res){
        res.send('您好我是:app')
})

// app.listen(3000, () => console.log('running...'))
app.listen(3000, function(){
        console.log('running...')
})

启动服务:

cmd 命令行中输入: nodemon app.js 

ok项目启动 浏览器打开 
基本的服务搭建完成

项目使用的插件

axios

npm install axios --save

注意引入index.js

asynchronous 异步

疫情接口( 仅学习使用)

https://voice.baidu.com/newpneumonia/get?target=trend&isCaseIn=0&stage=publish&callback=jsonp_1595142630965_83751(jsonp格式转换json格式)

app.get('/api', async function(req, res){
      //解决跨域问题
//   res.json({name:'lyx'})
let url = 'https://voice.baidu.com/newpneumonia/get?target=trend&isCaseIn=0&stage=publish&callback=jsonp_1595142630965_83751'
  let resdata = await axios.get(url)
        let data =resdata.data;
        // res.send(data)
       res.json(data) 
    
})

打开页面,可以看到数据

17-2 前端

  1. 初始化react项目包

    包含操作: npm init /npm webpack / 外加两个文件夹/ md说明文档/ 就是一个快捷操作

 create-react-app reactapp

  1. axios 前端安装 axiox 都自己的node_modules
npm install axios --save

注意引入app.js
const axios = require('axios')  

前端访问疫情接口:

		  async	componentWillMount(){
				console.log(0)
				// axios.get()
let url = 'https://voice.baidu.com/newpneumonia/get?target=trend&isCaseIn=0&stage=publish&callback=jsonp_1595142630965_83751'
 let resdata = await axios.get(url)
 let data =resdata.data;
 console.log(data);
			          }

跨域: 解决

 这就是搭建后台的原因:

async	 componentWillMount(){
        let url = 'http://localhost:4000/api'
         let resdata = await axios.get(url)
         let data_ = resdata.data.features

          this.setState({
            Newslistdata:data_
          })

        console.log('前台返回第一层数据',data_);	 
        }


页面结构

  1. 这里的4个tab切换,不是路由,而是在主页面中引入了4个子页面。 放在主页面的cont中,flex横向排列。

    点击tab,控制父盒子的定位左侧移动。

    2.实现点击tab bar动画: state准备:tabIndex,条件渲染tab,tab 设置点击事件,this.setState({})方式修改tabIndex,dom会根据数据变化,自动重新渲染。 4个tab移动意识一样。

    1. new页面的数据,为自己请求的数据。

    2. 图片的引入和使用: 引入后的变量 : src = {变量}

      import Bannerimg from ‘./assets/img/newbanner.jpg’;

      图片
import React from 'react';
import './assets/css/styls.css';

import NewsCom from './new';
const axios = require('axios')  

function Map() {
	return(
		<div className = 'cont_item'>
			<h1>我是map组件</h1>
		</div>
		
	)
}


	class App extends React.Component{
		constructor(props){
			super(props)
			this.state = {
				msg:'lyx',
				navlist:['疫情地图','最新进展','广州疫情','新闻内容'],
				tabIndex:0,
				barStyle:{
					"left":"22px"
				},
				contStyle:{
					"transform" :"translate(0,0)"
				}

			}
		}
	// ------------------------------------------

		

		 render(){
		var navjsx=	this.state.navlist.map((item,index)=>{
					if(index === this.state.tabIndex){
						return(
							<div className = "navItem active" onClick = {(event)=>{this.tabClickEvent(index)}} key ={index}>
								{item}
							</div>
						)	
					}else{
						return(
							<div className = "navItem" onClick = {(event)=>{this.tabClickEvent(index)}}   key ={index}>
								{item}
							</div>
						)	
					}
			})
			 return (
			 <div className = "App">
			 		<div className= "nav ">
						 <div className= 'bar' style = {this.state.barStyle}></div>
						{navjsx}
					 </div>

					 <div className="cont" style ={this.state.contStyle}>
						<NewsCom></NewsCom>
						<Map></Map>
					 </div>
					
			 </div>
			  );
		 }
	// ----------	 ---------- 
	tabClickEvent = (index)=>{
				this.setState({
					barStyle:{
						"left":(index*88+22)+"px"
					},
					contStyle:{
						"transform" :`translate(${-index*375}px,0)`
					}

				})
		
	}
	
}

export default App;


解析:

18 插槽

组件中写入内容,这些内容可以被识别和控制。 Recat需要自己开发支持插槽的功能。

原理: 在父页面 引入的子组件组件中写入的HTML, 会挂载到放到子组件 props中。

import React from 'react';
import ReactDOM from 'react-dom';




class Children extends React.Component {

  constructor(props) {
    super(props)
   this.state = {
   
   }}

        render(){
          console.log(this);
      //2. 在子元素的this。props中则挂载了插槽了的数据。 属性值和jsx,
      // 所以可以实现条件渲染在自己的dom中。
          return(
            <div className = 'Children-dom'>
                <h1>我是chidren</h1>
            {this.props.children}
            </div> 
          )
        }

}
// --------------------

class Clock extends React.Component {
  constructor(props) {
    super(props)
   this.state = {
   fatherList : 'i is from father'
   }
  }
          render() {
           
              return(  
                <div>    
                  {this.props.children}
                      <h1>我是h1</h1>
                      <Children>  
             {/* 1. 插槽传值:在字标签中可以传入标签,dom 标签中的属性值,和state中的数据。 */}

                        <h1 data-id ='1'>我是parent的插槽 头部</h1>
                        <h1 data-id ='2'>我是parent的插槽 尾部</h1>
                          <span>  {this.state.fatherList}</span>
                      </Children>
                </div>
              )}

}


  ReactDOM.render(
    <Clock>
    </Clock> ,
    document.getElementById('root')
  );

19 路由

概念:

根据不同的路径,显示不同的组件(内容):React使用的库 react-router-dom;

安装:

npm install react-router-dom --save       (--save保存版本信息) 
                                              "react-router-dom": "^5.2.0",

ReaterRouter : 三大组件

Router: 所有路由租金的跟组件(底层组件),包裹路由规则的最外层容器。

Route:路由规则匹配组件,显示当前规则对应的组件。

Link: 路由跳转的组件。

注意: 如果要精确匹配,那么可以在route上设置 exacct 属性。(注意单词adj. 准确的,精密的;精确的)

路由的两种引入:

hash 模式

#/ #号就是hash的标志。 不发送请求

import { HashRouter as Router, Route , Link} from 'react-router-dom'

history 模式

/后边导向 需要后端配合

  引入
import {BrowserRouter as Router, Route , Link} from 'react-router-dom'


总结:

basename 设根路径

route 映射路由和组件 关系

link 相当于a标签跳转

0. exact 精准匹配。

第一种: 当有link标签时, 加载link中。
第二种: 没有link标签,只有route 标签时,加在route中。

 <Link to = '/product' exact>产品页</Link>
<Route path =  "/"    component = { ()=> (   <div> 首页1</div>) }></Route>



<Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route>
                                               

基本的路由模式 code

1. 常规的路由link跳转 和传值

APP.js 组件页面 挂载到index.js 主页面中

import React from 'react';
import ReactDOM from 'react-dom';

import {BrowserRouter as Router, Link, Route} from 'react-router-dom'


function Me(props){
  console.log(props);
  return(
        <h1>Me</h1>
  )
}

function Home(props){
  console.log(props);
  return(
        <h1>Home</h1>
  )
}



function Produc(props){
  console.log(props);
  return(
        <h1>Produc</h1>
  )
}


  class App extends React.Component {
  constructor(props) {
    super(props)
   this.state = {
  
   }
  }
    render(){
      return(   

  <div id = 'app'>    
           <div> 所有页面都显示的普通页面</div>
   
   
         <Router >   
        
         <div className = 'nav'>
      
             <Link to = { { pathname:"/",search:"?sername=admin",hash:"#abc",state:{msg:"helloworld"}} }>Home</Link>
             <Link to = '/product'>产品页</Link>
             <Link to = '/me'>个人中心</Link>
         </div>
   
             <Route path = "/" exact component = {Home}></Route>
             <Route path =  "/product" component = {Produc}></Route>
             <Route path =  "/me" component = {Me}></Route>
   
         </Router>   
   </div>
 
      )
   
}
}
export default App;

Link to = { 变量}
         <Router >   
         <div className = 'nav'>
             <Link to = { { pathname:"/",search:"?sername=admin",hash:"#abc",state:                                       {msg:"helloworld"}} }>Home</Link>
         
         </div>
             <Route path = "/" exact component = {Home}></Route>
         </Router> 

1. link to  后面的path和route标签,映射关系。
2. exact 精准匹配。  否则 /me 页面会显示  /的页面。
3. link传递的值。可以在组件中收到


        function Home(props){
          console.log(props);
          return(
                <h1>Home</h1>
          )
        }

点击会自动拼接
http://localhost:3000/?sername=admin#abc

2 path 传值

通过路由标签,link传值, route : 键值, 组件中props对象中可以看到params下的值。

        <Router >   
         <div className = 'nav'>
            <Link to = '/me/12345' replace >个人中心</Link>
         </div>
            <Route path =  "/me/:id"    component = {Me}></Route>
         </Router> 

浏览器地址
http://localhost:3000/me/12345

3. Link 的 replace 路由切换跳转

替换栈 。 使用方法: 直接在Link 标签后内添加 replace 替换 属性。

        <Router >   
         <div className = 'nav'>
             <Link to = '/me' replace >个人中心</Link>
         </div>
             <Route path =  "/me"    component = {Me}></Route>
         </Router> 

路由跳转,replace / push 区别

 push: a-b-c 可以回到上一级
 例: this.props.history.push('路由地址')

replace: a-b-c 回不到上一级 适用于登录后,不需要重新回到登页面
 例: this.props.history.replace('路由地址')

4 重定向组件

形式也是一个组件,所以也有props 对象。

概念: 如果访问到某个组件时,如果有重定向组件,那么就会修改页面路径,使得页面内容显示未错定向路径的内容。

引入 Redirect 方法

import {BrowserRouter as Router, Link, Route, Redirect} from 'react-router-dom'

原理:

假设 form表单登录的时候, 设置访问FormCom() 组件,这个组件就是登录页面,点击提交,

组件内设置 ajax请求,获取用户权限,携带信息,跳转LoginInfo 组件, 组件内 标签 ,跳转到 登录或者是 首页。

import React from 'react';
// import ReactDOM from 'react-dom';

import {BrowserRouter as Router, Link, Route, Redirect} from 'react-router-dom'



function LoginInfo(props){    //重定向组件 

  if(props.location.state.login_state == 'success'){
    // 如果成功 定向到admin页面
    return <Redirect to = "/admin"> </Redirect> 
  }else{
    return <Redirect to = "/login"></Redirect> 
  }
}


function FormCom(){
   let dataobj = {
     pathname:"LoginInfo",
     state:{
       login_state:'success'
     }
   }

    return(
<div>
  <h1>表单验证模拟</h1>
    <Link to = {dataobj }>点击跳转至LoginInfo控制组件</Link>
    
</div>
    )
}

  class App extends React.Component {
    render(){
      return(   

            <div id = 'app'> 
          
         <Router >   
          <Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route>
          <Route path =  "/form" exact  component = { FormCom }></Route>
          <Route path =  "/login" exact  component = { ()=> (   <div> login请重新登陆                           </div>) }>
          </Route>
          <Route path =  "/LoginInfo" exact  component = { LoginInfo }></Route>
          <Route path =  "/admin" exact   component = { ()=> (   <div> admin登录成功到                              admin</div>) }>
        </Route>
   
         </Router>   
   </div>
 
      )
}
}

export default App;





5 Switch (n. 开关) 匹配 only one

应用场景:

路由会一直匹配,直到查找完所有的路由映射。

1.假设没有exact 精准匹配, 进入home 首页也会显示。
 <Route path =  "/" 
 <Route path =  "/home" 
2.有exact 精准匹配,碰到两个path相同的,又会同时显示两个页面内容。
 <Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route>  
  <Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route>
 
                                                 
 Switch 作用: 匹配一条route,符合要求,就停止匹配。                                                                                          

使用方式:

引入  Switch 方法  注意模块都是首字母大写

import {BrowserRouter as Router, Link, Route, Redirect, Switch} from 'react-router-dom'


包裹route 使用。
<Router >   
           <Switch>
          <Route path =  "/"  exact  component = { ()=> (   <div> 首页1</div>) }></Route>
           </Switch>
</Router> 



6 编程式路由 js控制

1. push ( ) 跳转

子页面,点击跳转同时携带数据, 传值



class Children extends React.Component {

  render(){
    return(   
          <div id = 'Children'>    
        <button onClick = { this.clickEvent}>  跳转到首页</button>
            我是 Children
        </div>
    )
  }
        clickEvent=()=>{  
            console.log(this.props.history.push("/",{name:"这是chilren传递的数据"}))
          }
          // push( ) 接受两个参数  第一个时路由path , 第二个是: 可以页面传值  目标组件的 props中的location-state 下挂载

  }

replace
go
clickEvent=()=>{  
          //  this.props.history.push("/",{name:"这是chilren传递的数据"})
          //  this.props.history.replace("/",{name:"这是chilren传递的数据"})
          this.props.history.go(-1)  //正数前进,负数后退。 历史堆栈中要有数据,否则不能跳转。

          }

7 动态路由

解析:

正常老说: path = “/” 只能在 localhost:3000/ 时可以访问。 不能加参数

path = “/:id” 这种, 后边可以加参数,变化的参数也可以。 动态。

同样 props中可以查看数据

<Route path =  "/:id"  exact  component = { shouye }></Route>


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/104170.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux msend.pl配置

1.概述 1.1.说明​​​​​ 本文细描述Linux环境下(arm架构x64)基于perl的msend.pl配置,以实现根据msend.pl进行告警事件的发送。 1.2.环境说明 OS Version:RHEL7.6(arm架构x64) Perl Version: v5.16.3 1.3.msend.pl架构图 2.msend.pl配置 2.1.msend.pl配置 前提:以r…

小学数学作业练习册出题网站源码_支持打印转成PDF

小学数学作业练习册出题网站源码_支持打印转成PDF 小学数学出题网页版源码&#xff0c;加减乘除混合运算&#xff0c;支持自定义数字、小数、混合运算&#xff0c;支持加减乘除运算混合多选&#xff08;一道题中同时随机出现加减乘除运算符&#xff09;支持自定义出题数量&…

三、W5100S/W5500+RP2040树莓派Pico<TCP Client数据回环测试>

文章目录 1. 前言2. 协议简介2.1 简述2.2 优点2.3 应用 3. WIZnet以太网芯片4. TCP Client数据回环测试4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 测试现象 5. 注意事项6. 相关链接 1. 前言 在当今的计算机网络环境中&#xff0c;TCP&#xff08;传输控制协议&am…

R语言代码示例

以下是一个使用R语言和httrOAuth库的下载器程序&#xff0c;用于下载的内容。程序使用以下代码。 # 安装和加载必要的库 install.packages("httr") install.packages("httrOAuth") library(httr) library(httrOAuth) ​ # 设置 http_proxy <- "du…

软件测试面试1000问(含文档)

前前后后面试了有20多家的公司吧&#xff0c;最近抽空把当时的录音整理了下&#xff0c;然后给大家分享下 开头都是差不多&#xff0c;就让做一个自我介绍&#xff0c;这个不用再给大家普及了吧 同时&#xff0c;我也准备了一份软件测试视频教程&#xff08;含接口、自动化、…

XTU-OJ 1178-Rectangle

题目描述 给你两个平行于坐标轴的矩形&#xff0c;请判断两者是不是相交&#xff08;面积有重合的部分&#xff09;&#xff1f; 输入 第一行是一个整数K&#xff0c;表示样例数。 每个样例占两行&#xff0c;每行是4个整数&#xff0c;表示一个矩形的对角线点的坐标&#xff0…

蓝桥杯双周赛算法心得——铺地板(质因数)

大家好&#xff0c;我是晴天学长&#xff0c;这是第二周的蓝桥杯的双周赛&#xff0c;题可出的又好又灵活啊&#xff01;真不错&#xff01; 1) .铺地板 2) .算法思路 1.导入java.util包中的Scanner类&#xff0c;以从用户那里读取输入。 2.main方法是程序的入口点。 3.创建一…

MYSQL(事务+锁+MVCC+SQL执行流程)理解

一)事务的特性: 一致性:主要是在数据层面来说&#xff0c;不能说执行扣减库存的操作的时候用户订单数据却没有生成 原子性:主要是在操作层面来说&#xff0c;要么操作完成&#xff0c;要么操作全部回滚&#xff1b; 隔离性:是自己的事务操作自己的数据&#xff0c;不会受到到其…

sheng的学习笔记-【中】【吴恩达课后测验】Course 3 - 结构化机器学习项目 - 第一周测验

课程3_第1周_测验题 目录&#xff1a;目录 要解决的问题 ① 这个例子来源于实际项目&#xff0c;但是为了保护机密性&#xff0c;我们会对细节进行保护。 ② 现在你是和平之城的著名研究员&#xff0c;和平之城的人有一个共同的特点&#xff1a;他们害怕鸟类。 ③ 为了保护…

超级强大!送你几款Linux 下终极SSH客户端

更多IT技术&#xff0c;请关注微信公众号:“运维之美” 超级强大&#xff01;送你几款Linux 下终极SSH客户端 1.MobaXterm2.Xshell3.SecureCRT4.PuTTY5.FinalShell6.Termius7.WindTerm 安全外壳协议&#xff08;Secure Shell&#xff0c;简称 SSH&#xff09;是一种网络连接协议…

线性代数1:线性方程和系统

Digital Collection (staedelmuseum.de) 图片来自施泰德博物馆 一、前言 通过这些文章&#xff0c;我希望巩固我对这些基本概念的理解&#xff0c;同时如果可能的话&#xff0c;通过我希望成为一种基于直觉的数学学习方法为其他人提供额外的清晰度。如果有任何错误或机会需要我…

【Overload游戏引擎细节分析】standard材质Shader

提示&#xff1a;Shader属于GPU编程&#xff0c;难写难调试&#xff0c;阅读本文需有一定的OpenGL基础&#xff0c;可以写简单的Shader&#xff0c;不适合不会OpenGL的朋友 一、Blinn-Phong光照模型 Blinn-Phong光照模型&#xff0c;又称为Blinn-phong反射模型&#xff08;Bli…

苹果将于8月31日举行今秋的第二场发布会

在今日凌晨&#xff0c;苹果宣布&#xff0c;将于北京时间10月31日早上8点举行今秋的第二场发布会&#xff0c;主题为“来势迅猛”。据多方猜测苹果本次活动的核心产品大概率是搭载全新M3芯片的Mac系列产品。 据了解&#xff0c;在苹果的产品线中&#xff0c;搭载M3芯片的Mac系…

Stable Diffusion WebUI扩展canvas-zoom详细讲解

canvas-zoom这是什么? 这是一个针对画布做一些操作的工具,比如缩放等。 下面来详细说一下这些操作的热键。 重要的热键: 缩放(Alt+滚轮)、移动画布 (F)、全屏 (S) 和重置缩放 (R) (1)Shift + wheel - 缩放画布 按住Shift + 滚轮之后,一点反应都没有,之后按…

vue3检测是手机还是pc端,监测视图窗口变化

1.超小屏幕&#xff08;手机&#xff09; 768px以下 2.小屏设备&#xff08;平板&#xff09; 768px-992px 3.中等屏幕&#xff08;旧式电脑&#xff09; 992px-1200px 4.大屏设备&#xff08;现代电脑&#xff09; 1200px以上 <script setup name"welcome"> i…

Games104现代游戏引擎笔记 网络游戏架构基础

挑战1:网络同步 挑战2:是网络的可靠性&#xff0c;包括应对网络的延迟&#xff0c;丢包和掉线 挑战3: 反作弊和安全系统&#xff0c;因为网络游戏的本质是经济系统 挑战4:多样性(不同设备&#xff0c;不同服务器)&#xff0c;在不停服的情况下热更新 挑战5:大量人数时对高并发…

为什么POST请求经常发送两次?

大多数初级前端程序员&#xff0c;在通过浏览器F12的调试工具调试网络请求时&#xff0c;可能都会有一个发现&#xff0c;在进行POST请求时&#xff0c;明明代码里只请求了一次&#xff0c;为什么network里发送了两次呢&#xff0c;难道我代码出bug了&#xff1f;带着疑问点开第…

javascript原生态xhr上传多个图片,可预览和修改上传图片为固定尺寸比例,防恶意代码,加后端php处理图片

//前端上传文件 <!DOCTYPE html> <html xmlns"http://www.w3.org/1999/xhtml" lang"UTF-8"></html> <html><head><meta http-equiv"Content-Type" content"text/html;charsetUTF-8;"/><title…

npm改变npm缓存路径和改变环境变量

在安装nodejs时&#xff0c;系统会自动安装在系统盘C&#xff0c; 时间久了经常会遇到C盘爆满&#xff0c;有时候出现红色&#xff0c;此时才发现很多时候是因为npm 缓存保存在C盘导致的&#xff0c;下面就介绍下如何改变npm缓存路径。 1、首先找到安装nodejs的路径&#xff0c…

【微信小程序】实现投票功能(附源码)

一、Vant Weapp介绍 Vant Weapp 是一个基于微信小程序的组件库&#xff0c;它提供了丰富的 UI 组件和交互功能&#xff0c;能够帮助开发者快速构建出现代化的小程序应用。Vant Weapp 的设计理念注重简洁、易用和高效&#xff0c;同时提供灵活的定制化选项&#xff0c;以满足开发…