react

90 阅读2分钟

一.react 生态圈

  1. JSX 扩展的JS,react强依赖
  2. Flux(相当于VUEX,用的少)
  3. Redux(相当于VUEX,经常用)
  4. react-Native 开发移动端
  5. react-Server 在服务端渲染

二.script 引入react开发

1.公共引入文件

<script src="browser.js" charset="utf-8"></script>
<script src="react.development.js" charset="utf-8"></script>
<script src="react-dom.development.js" charset="utf-8"></script>

2.简单的渲染页面

<body>
    <div id="div1"></div>
</body>

<script type="text/babel">
    let root=document.getElementById('div1');
    ReactDOM.render(
      <div>
        <label htmlFor="user">用户名:</label>
        <input id="user" type="text" />
      </div>,
      root
    );
  </script>

3.组件

<body><div id="div1"></div></body>

  <script type="text/babel">
    class Cmp1 extends React.Component{
      constructor(...args){
        super(...args);
        this.name='blue';
        this.age=18;
      }
      fn(){
        return 'aaa';
      }
      //render(){
        //let arr=[];
        //for(let i=0;i<6;i++){
          //arr.push(
            //<li key={i}>{i}</li>
          //);
        //}
        //return (
         // <div>
          //  姓名:{this.name}<br/>
         //   年龄:{this.age+5}<br/>
          //  <ul> {arr} </ul>
         // </div>
        //);
     // }
      render(){
        let datas=[
          {name: 'blue', age: 18},
          {name: 'zhangsan', age: 25},
          {name: 'lisi', age: 28},
        ];
        return (
          <div>
            <ul>
              {datas.map((data,index)=>(
                <li key={index}>
                  姓名:{data.name}<br/>
                  年龄:{data.age}
                </li>
              ))}
            </ul>
          </div>
        );
      }
    }
    let root=document.getElementById('div1');
    ReactDOM.render(
      <div>
        <label htmlFor="user">用户名:</label>
        <input id="user" type="text" />
        <Cmp1></Cmp1>
      </div>,
      root
    );
  </script>

4.父子组件及传参

<body><div id="div1"></div></body>
  <script type="text/babel">
      //父组件
    class Parent extends React.Component{
      constructor(...args){
        super(...args);
      }
      render(){
        return (
          <ul>
            {this.props.arr.map((str,index)=><Child txt={str} key={index}/>)}
          </ul>
        );
      }
    }
    //子组件
    class Child extends React.Component{
      constructor(...args){
        super(...args);
      }
      render(){
        return (
          <li>
            {this.props.txt}
          </li>
        );
      }
    }
    let root=document.getElementById('div1');
    ReactDOM.render(
      <div>
        <label htmlFor="user">用户名:</label>
        <input id="user" type="text" />
        //渲染
        <Parent arr={['dfsdf', 'sdfsdf', 'werwer']} />
      </div>,
      root
    );
  </script>

5.传参误区

注意:1.传入的参数 this.props获取,是只读的不能够修改。2.this.state是组件内部的状态可以修改

class Cmp1 extends React.Component{
  constructor(...args){
    super(...args);
    this.state={a: 0};
  }
  fn(){
     //此参数状态为组件传入值this.props.a 是只读状态不能修改 所以报错
    this.props.a++;
    //此为组件内部状态可以修改 setState修改后并重新渲染组件
    this.setState({
      a: this.state.a+1
    });
  }
  render(){
    return (
      <div>
        <input type="button" value="+1" onClick={this.fn.bind(this)} />
        1.不变:{this.props.a} 
        2.会变:{this.state.a}
      </div>
    );
  }
}
let root=document.getElementById('div1');
ReactDOM.render(
  <div>
    <Cmp1 a={0} />
  </div>,
  root
);

6.组件通信(父组件获取子组件)

//父组件
class Parent extends React.Component{
  constructor(...args){
    super(...args);
  }
  fn(){
      //和vue类似 子组件定义ref来获取子组件的方法或属性
    this.refs['child1'].add(7);
  }
  render(){
    return (
      <div>
        <input type="button" value="+1" onClick={this.fn.bind(this)} />
        <Child ref="child1"/>
      </div>
    );
  }
}
//子组件
class Child extends React.Component{
  constructor(...args){
    super(...args);
    this.state={a: 0};
  }
  add(n){
    this.setState({
      a: this.state.a+n
    });
  }
  render(){
    return ( <div>{this.state.a}</div> );
  }
}
//渲染dom
let root=document.getElementById('div1');
ReactDOM.render(
  <div><Parent a={0} /></div>,
  root
);

7.组件通信(子组件获取父组件)

//父组件
class Parent extends React.Component{
  constructor(...args){
    super(...args);
    this.state={a: 0};
  }
  add(n){
    //修改父组件内部状态
    this.setState({
      a: this.state.a+n
    });
  }
  render(){
    return (
      <div>
        {this.state.a}
        <Child parent={this}/>
      </div>
    );
  }
}
//子组件
class Child extends React.Component{
  constructor(...args){
    super(...args);
  }
  render(){
    return (
      <div>
        <input type="button" value="+1" onClick={function (){
          //1.在父组件件里的子组件上定义属性parent并把this传入
          //2.通过this.props.parent来获取父组件的属性或方法  
          this.props.parent.add(11)
        }.bind(this)} />
      </div>
    );
  }
}
//渲染dom
let root=document.getElementById('div1');
ReactDOM.render(
  <div><Parent a={0} /></div>,
  root
);

8.组件的生命周期

react生命周期.png 子组件渲染完成后,父组件才算渲染完成

//父组件
class Parent extends React.Component{
  constructor(...args){
    super(...args);

    this.state={a: 0};
  }
  componentDidMount(){
    console.log('父组件已经挂载');
  }
  componentDidUpdate(){
    console.log('父组件已经更新');
  }
  componentWillUnmount(){
      console.log("组件销毁时执行")
  }
  fn(){
    this.setState({
      a: this.state.a+3
    });
  }
  render(){
    return (
      <div>
        <input type="button" value="+1" onClick={this.fn.bind(this)} />
        <Child a={this.state.a}/>
      </div>
    );
  }
}
//子组件
class Child extends React.Component{
  constructor(...args){
    super(...args);
  }
  componentDidMount(){
    console.log('子组件已经挂载');
  }
  componentDidUpdate(){
    console.log('子组件已经更新');
  }
  render(){
    return (
      <div>
        {this.props.a}
      </div>
    );
  }
}
//渲染dom
let root=document.getElementById('div1');
ReactDOM.render(
  <div><Parent /></div>,
  root
);

9.redux - 集中状态管理

  1. provider 1.整个redux最外层集中的作用域。2.包在最外层
  2. connect 状态的映射
  3. reducer 状态对象 多个reducer管不同对象 4.action状态的更新 (字符串或对象等)

安装:

要安装redux和react-redun
1.yarn add redux
2.yarn add react-redun

使用:
1.在index.js中

//在最外层文件(eg:index.js)中引入
import { createStore } from "redux"
import { Provider } from "react-redux"

//1.创建存储
function reducer1(state={name:"blue",age:18},action){
  switch (action.type) {
    case "set_name":
      //state.name = action.name  这样写改不了
      //修改方式必须是新的对象  用下面的name覆盖上面的name
      return {
        ...state,
        name:action.name
      }
    case "add_age":
      return {
        ...state,
        age:state.age + action.age
      }
    default:
      return state
  }

}
//2.创建存储对象
const store = createStore(reducer1)

ReactDOM.render(
  <React.StrictMode>
      //3.用Provider包裹整个App组件  在App里所有组件都可使用store
    <Provider store={store}>
      <App a={15} b={10} name="张三"/>
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

2.在App.js中

import React from "react";
import { connect } from 'react-redux';

class Cmp1 extends React.Component {
    fn (){
        this.props.setName("张三")
    }
    addFn (){
        this.props.addAge(6)
    }
    render (){
        return (
            <div>
                <input type="button" value="改名" onClick={this.fn.bind(this)}/>
                {this.props.name}
                <input type="button" value="加6" onClick={this.addFn.bind(this)}/>
                {this.props.age}
            </div>
        )
    }
}

//connect连接全局的属性
//connect两个参数 第一个是合并state和props 第二个是个json对象 action修改
export default connect(function(state,props){
   //state为全局的store数据,
  //props为本组件传入的数据
  //console.log(state,props)
    return {
        ...state,
        ...props
    }
},{
    setName (newName){
       //修改传入的name
        return {
            type:'set_name',
            name:newName
        }
    },
    addAge (n){
    //修改传入的age
        return {
            type:'add_age',
            age:n
        }
    }
})(Cmp1)