React组件——class组件和函数组件

〇、组件和元素的区别

// 这是React元素,
const div=React.createElement("div",...);

//这是React组件, 
const Div=()=>React.createElement("div",...);
复制代码

当你在代码中写了一个<div className="red">这是div</div>
babel会将其转译为React.createElement("div",{className:red},"这是div")

假如你定义了一个组件

const Welcome=()=> <div className="red">这是div</div>
<Wecome/>  //等价于 React.createElement(Welcome, null);
复制代码

一.使用prop传参数(外部数据传参)

function App(){
    return (
        <div className="App">
            爸爸
            <Son mesforSon="这是儿子"/>  
        </div>
    )
}

//class组件传参,直接对标签写一个想要的属性,然后this.props.xxx读取属性
class Son extends React.Component{
    render(){
        return (
            <div className="Son">
                儿子组件传入了参数: {this.props.mesforSon}
                <Grandson mesforGrandson="这是爷爷"/>
            </div>
        )
    }
}

//函数组件传参,传入的参数被视为props,props.xxx获取属性
const Grandson=(props)=>{
    return (
        <div className="Grandson">
           爷爷组件传入了参数: {props.mesforGrandson}
        </div>
    )
}

const root=document.querySelector("#App");
ReactDOM.render(<App/>,root);
复制代码

image.png


二.state传参(内部数据)

function App(){
  return (
    <div className="App">
    爸爸
    <Son/>
    </div>
  )
}
//class组件写法
class Son extends React.Component{
    constructor(){
        // 注意super()继承
        super();
        this.state={
            n:0
        }
    }
    add(){
        //重新设置state不是在原state上修改数据,而是创建一个新的state对象,代表state的改变
        this.setState({n:this.state.n+1});
        //如遇到要写复杂的情况,setState里最好写一个函数,避免异步函数带来的数据更新不及时
        this.setState((state)=>{
            const n=state.n+1;
            console.log(n);
            return {n};
        });
        //上面的情况是打印出n,如果使用第一种方法set完后log,n还是之前的值,因为setState是异步函数
    }
    render(){
         //直接调用this.state读数据
        return (
          <div className="Son">    
            儿子 n:{this.state.n}
            <button onClick={()=>this.add()}>+1</button>
            <Grandson/>
          </div>
        )
    }
}
//函数组件写法
const Grandson=()=>{
    //useState会暴露两个接口,读接口和写接口,里面0为初始值
    const [n,setN]=React.useState(0); 
    return (
        <div className="Grandson">
            孙子 n:{n}
            <button onClick={()=>setN(n+1)}>+1</button>
        </div>
    )
    //setN不会改变元素的n,会生成一个新的n
}

const root=document.querySelector("#App");
ReactDOM.render(<App/>,root);
复制代码

image.png


三.state传复杂参数

1. 类组件传两(多)个参数

class Son extends React.Component{
    constructor(){
        super();
        this.state={
            m:0,
            n:0
        }
    }
    addN(){
        this.setState({n:this.state.n+1});
        //可以只写对n修改,m不会被设为undefined
        //相当于 this.setState({...this.state,n:this.state.n+1})
    }
    addM(){
        this.setState({m:this.state.m+1});
        //同理
    }
    render(){
        return(
            <div className="Son">
                儿子 m:{this.state.m}
                <button onClick={()=>this.addM()}>m+1</button>
                n:{this.state.n}
                <button onClick={()=>this.addN()}>n+1</button>
            </div>
        )    
    }
}
复制代码

注意,class组件只能合并state中的第一层属性,假如后面有第二层或多层属性,则会出问题,要用…操作符拷贝所有属性再改

2.函数组件传复杂参数

const GrandSon=()=>{
    //函数组件分开写数据useState最好
    const [n,setN]=React.useState(0);
    const [m,setM]=React.useState(0);
    return(
        <div className="GrandSon">
            孙子 n:{n}
            <button onClick={()=>setN(n+1)}>n+1</button>
            m:{m}
            <button onClick={()=>setM(m+1)}>m+1</button>
        </div>
    )
}
复制代码

注意,函数组件不适合将所有数据统一写在state里面

const GrandSon=()=>{
    const [state,setState]=React.useState({n:0,m:0});
    return(
        <div className="GrandSon">
            孙子 n:{state.n}
            <button onClick={()=>setState({...state,n:state.n+1})}>n+1</button>
            m:{state.m}
            <button onClick={()=>setState({...state,m:state.m+1})}>m+1</button>
        </div>
    )
    //注意这个setState,要用...state把所有的值都拷贝进去,这个与函数组件是不同的
}
复制代码

四.事件绑定

1.类组件的事件绑定

image.png

最好要以箭头函数()=>this.addN()的形式绑定事件。原因很简单,绑定的事件都是异步函数,普通函数里的this在调用时会成null,最后指向window。

于是最好的写法

class Son extends React.Component{
    constructor(){
        super();
        this.state={
            m:0,
            n:0
        }
        //方法一:addN函数直接改写成箭头函数,放在constructor里面,相当于变量
        this.addN=()=> this.setState({n:this.state.n+1});
    }
       //方法二:addM函数直接在外部改成箭头函数(推荐)
    addM=()=> this.setState({m:this.state.m+1});
    render(){
        return(
            <div className="Son">
                儿子 m:{this.state.m}
                <button onClick={this.addM}>m+1</button>
                n:{this.state.n}
               <button onClick={this.addN}>n+1</button>
            </div>
        )    
    }
    //就可以直接绑定事件了
复制代码

这个的原理,参考 class中普通函数和箭头函数的区别:

class中的普通函数在原型上,箭头函数会在对象上

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享