〇、组件和元素的区别
// 这是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);
复制代码
二.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);
复制代码
三.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.类组件的事件绑定
最好要以箭头函数()=>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