定义组件的两种方式
- 函数定义
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
- 类定义
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
使用React时,值得注意的点:
所有的React组件必须像纯函数那样使用它们的props,不要修改传入的props。(纯函数,也就是不改变传入值的函数)
正确使用状态:关于
setState()
有三点值得注意:
- 不要直接更新状态,使用
setState()
更新
// Correct
this.setState({comment: 'Hello'});
- 状态更新可能是异步的(
this.props
,this.state
可能异步更新,不应依靠它们去计算新的state值),如
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
可使用setState()
的第二种形式,传入一个函数(函数的第一个参数为上一个state的值,第二个参数为此次更新的props)
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
- 状态更新合并
当你调用setState()
时,React 将你提供的对象合并(浅合并)到当前状态。
(这里的浅合并是什么意思??)
数据自顶向下流动
任何状态始终由某些特定组件所有,并且从该状态导出的任何数据或 UI 只能影响树中下方的组件。
父组件或子组件都不能知道某个组件是有状态还是无状态,并且它们不应该关心某组件是被定义为一个函数还是一个类。这就是为什么状态通常被称为局部或封装。 除了拥有并设置它的组件外,其它组件不可访问。
组件可以选择将其状态作为属性传递给其子组件。事件处理:若用类的方法,需要绑定事件的this
// 两种绑定this方法
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
值得注意的是,通过 bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面
class Popper extends React.Component{
constructor(){
super();
this.state = {name:'Hello world!'};
}
preventPop(name, e){ //事件对象e要放在最后
e.preventDefault();
alert(name);
}
render(){
return (
<div>
<p>hello</p>
{/* Pass params via bind() method. */}
<a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
</div>
);
}
}
- 阻止组件渲染:让 render 方法返回 null 而不是它的渲染结果即可实现。
- key会作为给React的提示,但不会传递给你的组件。如果需要使用和key相同的值,请将其作为属性传递
const content = posts.map((post) =>
<Post
key={post.id}
id={post.id}
title={post.title} />
);
受控组件:在React中,可变的状态通常保存在组件的状态属性中,并且只能用
setState()
方法进行更新。我们通过使react变成一种单一数据源的状态来结合二者。React负责渲染表单的组件仍然控制用户后续输入时所发生的变化。相应的,其值由React控制的输入表单元素称为“受控组件”。状态提升:状态都是首先添加在需要渲染数据的组件中。此时,如果另一个组件也需要这些数据,你可以将数据提升至离它们最近的父组件中。你应该在应用中保持自上而下的数据流,而不是尝试在不同组件中同步状态。
组合VS继承:建议使用组合而不是继承来复用组件之间的代码。
一些组件不能提前知道它们的子组件是什么。这些组件使用 children 属性将子元素直接传递到输出。
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
请记住,组件可以接受任意元素,包括基本数据类型、React 元素或函数。