1.组件使你可以将ui划分为一个一个独立,可复用的小部件,并可以对每个部件进行单独的设计。
2.从定义上来说,组件就像JavaScript的函数,组件可以接收任意输入(成为“props”),并返回react元素,用以描述屏幕显示内容。
PS:可以把组件看出一个一个的函数,props就是一个传入到函数的对象参数,里面就是组件所需的一个一个的变量。state就是函数内部定义的变量,可以直接操作
3.组件名称总是以大写字母开始。PS:<div/>代表一个DOM标签,而<welcome/>则代表一个组件,并且需要在 作用域中 有一个Welcome组件
4.提取组件:不要害怕把一个组件分为多个更小的组件,因为过分复杂的组件一方面不利于复用,修改起来也麻烦,所以可以根据情况将其分解为多个小的组件,注意组件的名称定义要从组件本身的角度命名,而不是他被使用的上下文环境。
提取组件可能看起来是一个繁琐的工作,但是在大型的 Apps 中可以回报给我们的是大量的可复用组件。一个好的经验准则是如果你 UI 的一部分需要用多次 (Button,Panel,Avatar),或者本身足够复杂(App,FeedStory,Comment),最好的做法是使其成为可复用组件。
5.Props是只读的。无论你用函数或类的方法来声明组件,它都无法修改其自身props。所有react组件必须都是纯函数,并禁止修改其自身props。如果有UI的需求,需要动态的改变,可以使用state,state允许react组件在不违反规则的情况下,根据用户操作,网络影响,或者其他随便什么东西,来动态改变其输出
6.更新UI的方式:
1.ReactDOM.render()方法来更新渲染的输出
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(
element,
document.getElementById('root')
);
}
setInterval(tick, 1000);
5.this.props 由 React 本身设定, 而 this.state 具有特殊的含义,但如果需要存储一些不用于视觉输出的内容,则可以手动向类中添加额外的字段。
如果在 render() 方法中没有被引用, 它不应该出现在 state 中。
注意我们把计时器ID直接存在 this 中。
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
我们来快速回顾一下该过程,以及调用方法的顺序:
当 <Clock /> 被传入 ReactDOM.render() 时, React 会调用 Clock组件的构造函数。 因为 Clock 要显示的是当前时间,所以它将使用包含当前时间的对象来初始化 this.state 。我们稍后会更新此状态。
然后 React 调用了 Clock 组件的 render() 方法。 React 从该方法返回内容中得到要显示在屏幕上的内容。然后,React 然后更新 DOM 以匹配 Clock 的渲染输出。
当 Clock 输出被插入到 DOM 中时,React 调用 componentDidMount() 生命周期钩子。在该方法中,Clock 组件请求浏览器设置一个定时器来一次调用 tick()。
浏览器会每隔一秒调用一次 tick()方法。在该方法中, Clock 组件通过 setState() 方法并传递一个包含当前时间的对象来安排一个 UI 的更新。通过 setState(), React 得知了组件 state(状态)的变化, 随即再次调用 render() 方法,获取了当前应该显示的内容。 这次,render() 方法中的 this.state.date 的值已经发生了改变, 从而,其输出的内容也随之改变。React 于是据此对 DOM 进行更新。
如果通过其他操作将 Clock 组件从 DOM 中移除了, React 会调用 componentWillUnmount() 生命周期钩子, 所以计时器也会被停止。
6.正确地使用 State(状态)
关于 setState() 有三件事是你应该知道的:
(1) 不要直接修改 state(状态)
例如,这样将不会重新渲染一个组件:
// 错误
this.state.comment = 'Hello';
用 setState() 代替:
// 正确
this.setState({comment: 'Hello'});
唯一可以分配 this.state 的地方是构造函数。
(2)state(状态) 更新可能是异步的
React 为了优化性能,有可能会将多个 setState() 调用合并为一次更新。
因为 this.props 和 this.state 可能是异步更新的,你不能依赖他们的值计算下一个state(状态)。
例如, 以下代码可能导致 counter(计数器)更新失败:
// 错误
this.setState({
counter: this.state.counter + this.props.increment,
});
要弥补这个问题,使用另一种 setState() 的形式,它接受一个函数而不是一个对象。这个函数将接收前一个状态作为第一个参数,应用更新时的 props 作为第二个参数:
// 正确
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
我们在上面使用了一个[箭头函数]但是也可以使用一个常规的函数:
// 正确
this.setState(function(prevState, props) {
return {
counter: prevState.counter + props.increment
};
});
(3)state(状态)更新会被合并
当你调用 setState(), React 将合并你提供的对象到当前的状态中。
例如,你的状态可能包含几个独立的变量:
constructor(props) {
super(props);
this.state = {
posts: [],
comments: []
};
}
然后通过调用独立的 setState() 调用分别更新它们:
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
合并是浅合并,所以 this.setState({comments}) 不会改变 this.state.posts 的值,但会完全替换this.state.comments 的值。
7.数据向下流动
无论作为父组件还是子组件,它都无法获悉一个组件是否有状态,同时也不需要关心另一个组件是定义为函数组件还是类组件。
这就是 state(状态) 经常被称为 本地状态 或 封装状态的原因。 它不能被拥有并设置它的组件 以外的任何组件访问。
一个组件可以选择将 state(状态) 向下传递,作为其子组件的 props(属性):
8.处理事件
通过 React 元素处理事件跟在 DOM 元素上处理事件非常相似。但是有一些语法上的区别:
React 事件使用驼峰命名,而不是全部小写。
通过 JSX , 你传递一个函数作为事件处理程序,而不是一个字符串。
在 React 中略有不同:
<button onClick={activateLasers}>
Activate Lasers
</button>
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 这个语法确保 `this` 被绑定在 handleClick 中
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
这个语法的问题是,每次 LoggingButton 渲染时都创建一个不同的回调。在多数情况下,没什么问题。然而,如果这个回调被作为 prop(属性) 传递给下级组件,这些组件可能需要额外的重复渲染。我们通常建议在构造函数中进行绑定,以避免这类性能问题。
网友评论