#react v16.2.0
react 16
componentWillMount可能会被执行多次。
Calling setState with null no longer triggers an update
setState callbacks (second argument) now fire immediately after componentDidMount / componentDidUpdate instead of after all components have rendered.
JSX
默认情况下, 在渲染之前, React DOM 会格式化(escapes) JSX中的所有值. 从而保证用户无法注入任何应用之外的代码. 在被渲染之前,所有的数据都被转义成为了字符串处理。 以避免 XSS(跨站脚本) 攻击
元素elements 是React应用中最小的构建部件(构建块,building blocks)。
关注每个时间点UI的表现, 而不是关注随着时间不断更新UI的状态, 可以减少很多奇怪的 bug 。
所有React组件都必须是纯函数(不改变自身的输入值),并禁止修改自身props
函数式组件(Functional)
//接收props参数,返回一个React元素
function Welcome(props){
return <h1>Hello,{ props.name }</h1>
}
类组件
//有额外的特性
//类允许在其中添加本地状态(state)和生命周期钩子
class Welcome extends React.Component{
render() {
return <h1>Hello, { this.props.name }</h1>;
}
}
diff
-
根元素类型不同全部重绘,state(状态)都会丢失
// 销毁旧的Counter,重新装载(remount)一个新的 <div> <Counter /> </div> <span> <Counter /> </span>
-
比较两个相同类型的React DOM,保留相同的底层DOM节点,只更新发生改变的属性(attributes)
// 只修改color,不修改fontWeight <div style={{color: 'red', fontWeight: 'bold'}} /> <div style={{color: 'green', fontWeight: 'bold'}} /> componentWillReceiveProps() => componentWillUpdate() => render()
-
递归处理子元素
key值作为同类型子节点的唯一识别码,避免插入引起的子节点全部重绘,提高渲染效率。
key值应该是稳定的,可预测的,唯一的。不稳定的 key (类似于 Math.random() 函数的结果)可能会产生非常多的组件实例并且 DOM 节点也会非必要性的重新创建。这将会造成极大的性能损失和组件内state的丢失。
受控组件
每一次state变化都会伴有相关联的处理函数,可以直接修改或验证用户的输入(onChange)
// onChange函数获取的value实际上是修改后的值,可能和当前页面显示的值不一样
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
//此处弹出的是修改后的值,并不是input里显示的value值
alert(event.target.value)
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.props.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
ReactDOM.render(
<NameForm value="1222" />,
document.getElementById('root')
);
组件包含
组件可以接受任意的 props(属性) ,包括原始值、React 元素,或者函数。如 和 等 React 元素本质上也是对象,所以可以将其像其他数据一样作为 props(属性) 传递使用。
如果要在组件之间重用非 U I功能,我们建议将其提取到单独的 JavaScript 模块中。组件可以导入它并使用该函数,对象或类,而不扩展它。
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<SplitPane left={<Contacts />} right={<Chat />} />
);
}
生命周期函数
首次渲染
-
构造函数(仅调用一次)
// es6 constructor(props){ super(props); } // es5 getDefaultProps() getInitialState(){ return {} }
-
componentWillMount()(仅调用一次)
??? 由componentWillMount 引发的血案(莫名其妙的报错,或者Action调用不执行,无法获取数据): UNSAFE_componentWillMount
* This is the only lifecycle hook called on server rendering. * This lifecycle was previously named componentWillMount. That name will continue to work until version 17. Use the rename-unsafe-lifecycles codemod to automatically update your components.
-
react16.0以后,componentWillMount可能会被执行多次。
-
componentWillMount中ajax参数错误会导致白屏,阻断页面渲染,连接报错则页面正常渲染;在 ajax success 中执行的操作会导致页面渲染暂停
-
渲染过程中出错似乎会尝试重新渲染组件一次,即 重新从willMount开始调用
-
willMount 里的setState会触发render(will not trigger an extra rendering),且setState的数据可在render中获取,缩短了渲染过程。但如果 componentWillMount 里setState 的数据是异步获取的,则渲染步骤和 componentDidMount 中获取数据并无不同。
didMount中的setState
componentDidMount (){ console.log('announce: willMount') this.setState({id: 2}, function(){ console.log('announce: setState') }); } announce: willMount announce: render undefined announce: announceListRender Pagination: willMount Pagination: didMount announce: didMount announce: render 2 announce: announceListRender Pagination: shouldComponentUpdate announce: didUpdate announce: setState
willMount中的setState
componentWillMount (){ console.log('announce: willMount') this.setState({id: 2}, function(){ console.log('announce: setState') }); } announce: willMount announce: render 2 announce: announceListRender Pagination: willMount Pagination: didMount announce: didMount announce: setState
-
-
render()
-
componentDidMount()(仅调用一次)
更新 (初次渲染不触发)
- componentWillReceiveProps(nextProps)
- shouldComponentUpdate(nextProps, nextStates)
- componentWillUpdate()
- render()
- componentDidUpdate()
setState: 猜测:setState的操作会立即改变数据 即 setState是同步的,但是,改变的数据可能会延迟等到下一次render的时候显示出来
// setState 的 callback 的输出位置在didUpdate之后
t.setState((prevState, props) => {
console.log('announce: setState')
}, () => {
console.log('announce: didSetState')
});
componentDidUpdate(){
console.log('announce: didUpdate')
}
强制更新
forceUpdate(skipping shouldComponentUpdate()。This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate() method of each child forceUpdate更新不受shouldComponentUpdate控制,但是forceUpdate引起render之后所有生命周期函数正常触发,包括子组件的shouldComponentUpdate)
销毁
componentWillUnmount()
reflux
Action
- many stores can listen for a single action
Store
- 每个Store是一个单例
- 可引入多个Store
- this.storeKeys 可以控制引入到组件内的 state,确保引入的 stores 不会覆盖组件内的 state
优势:可统一管理状态,可自由组合并选取需要的状态
react & redux chrome extension
自己下载源码 build extension
redux
react
--------------- 2018.6.7