React 笔记
Boolean 属性
省略一个属性的值会导致JSX把它当做 true。要传值 false必须使用属性表达式。这常出现于使用HTML表单元素,含有属性如disabled,required,checked 和 readOnly。
// 在JSX中,对于禁用按钮这二者是相同的。
<input type="button" disabled />;
<input type="button" disabled={true} />;
// 在JSX中,对于不禁用按钮这二者是相同的。
<input type="button" />;
<input type="button" disabled={false} />;
JSX 展开属性
如果你事先知道组件需要的全部 Props(属性),JSX 很容易地这样写:
var component = <Component foo={x} bar={y} />;
修改 Props 是不好的,明白吗
如果你不知道要设置哪些 Props,那么现在最好不要设置它:
var component = <Component />;
component.props.foo = x; // 不好
component.props.bar = y; // 同样不好
这样是反模式,因为 React 不能帮你检查属性类型(propTypes)。这样即使你的 属性类型有错误也不能得到清晰的错误提示。
Props 应该被认为是不可变的。在别处修改 props 对象可能会导致预料之外的结果,所以原则上这将是一个冻结的对象。
展开属性(Spread Attributes)
现在你可以使用 JSX 的新特性 - 展开属性:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
传入对象的属性会被复制到组件内。
它能被多次使用,也可以和其它属性一起用。注意顺序很重要,后面的会覆盖掉前面的。
var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
这个奇怪的 … 标记是什么?
这个 … 操作符(增强的操作符)已经被 ES6 数组 支持。相关的还有 ECMAScript 规范草案中的 Object 剩余和展开属性(Rest and Spread Properties)。我们利用了这些还在制定中标准中已经被支持的特性来使 JSX 拥有更优雅的语法。
State
组件其实是状态机(State Machines)
React 把用户界面当作简单状态机。把用户界面想像成拥有不同状态然后渲染这些状态,可以轻松让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。React 来决定如何最高效地更新 DOM。
State 工作原理
常用的通知 React 数据变化的方法是调用 setState(data,callback)。这个方法会合并(merge) data 到 this.state,并重新渲染组件。渲染完成后,调用可选的 callback 回调。大部分情况下不需要提供 callback,因为 React 会负责把界面更新到最新状态。
哪些组件应该有 State?
大部分组件的工作应该是从 props 里取数据并渲染出来。但是,有时需要对用户输入、服务器请求或者时间变化等作出响应,这时才需要使用 State。
尝试把尽可能多的组件无状态化。 这样做能隔离 state,把它放到最合理的地方,也能减少冗余,同时易于解释程序运作过程。
常用的模式是创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 props 传给子级。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。
哪些 应该 作为 State?
State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。 真实的应用中这种数据一般都很小且能被 JSON 序列化。当创建一个状态化的组件时,想象一下表示它的状态最少需要哪些数据,并只把这些数据存入 this.state。在 render() 里再根据 state 来计算你需要的其它数据。你会发现以这种方式思考和开发程序最终往往是正确的,因为如果在 state 里添加冗余数据或计算所得数据,需要你经常手动保持数据同步,不能让 React 来帮你处理。
哪些 不应该 作为 State?
this.state 应该仅包括能表示用户界面状态所需的最少数据。因些,它不应该包括:
计算所得数据: 不要担心根据 state 来预先计算数据 —— 把所有的计算都放到 render() 里更容易保证用户界面和数据的一致性。例如,在 state 里有一个数组(listItems),我们要把数组长度渲染成字符串, 直接在 render() 里使用 this.state.listItems.length + ’ list items’ 比把它放到 state 里好的多。
React 组件: 在 render() 里使用当前 props 和 state 来创建它。
基于 props 的重复数据: 尽可能使用 props 来作为实际状态的源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为 props 可能因为父组件重绘的结果而变化。
自动绑定(Autobinding)和事件代理(Event Delegation)
在幕后,React 做了一些操作来让代码高效运行且易于理解。
Autobinding: 在 JavaScript 里创建回调的时候,为了保证 this 的正确性,一般都需要显式地绑定方法到它的实例上。在 React,所有方法被自动绑定到了它的组件实例上(除非使用ES6的class符号)。React 还缓存这些绑定方法,所以 cpu 和内存都是非常高效。而且还能减少打字!
事件代理 : React 实际并没有把事件处理器绑定到节点本身。当 React 启动的时候,它在最外层使用唯一一个事件监听器处理所有事件。当组件被加载和卸载时,只是在内部映射里添加或删除事件处理器。当事件触发,React 根据映射来决定如何分发。当映射里处理器时,会当作空操作处理。参考 David Walsh 很棒的文章 了解这样做高效的原因。
传递 Props:捷径
有一些常用的 React 组件只是对 HTML 做简单扩展。通常,你想 复制任何传进你的组件的HTML属性 到底层的HTML元素上。为了减少输入,你可以用 JSX spread 语法来完成:
var CheckLink = React.createClass({
render: function() {
// 这样会把 CheckList 所有的 props 复制到 <a>
return <a {...this.props}>{'√ '}{this.props.children}</a>;
}
});
ReactDOM.render(
<CheckLink href="/checked.html">
Click here!
</CheckLink>,document.getElementById('example')
);
箭头函数=>
箭头函数就是个简写形式的函数表达式,并且它拥有词法作用域的this值(即不会新产生自己作用域下的this,arguments,super 和 new.target 等对象)。此外,箭头函数总是匿名的。
更短的函数
在一些函数式编程模式里,更短的函数书写方式很受欢迎。试比较:
var a = [
"Hydrogen","Helium","Lithium","Beryllium"
];
var a2 = a.map(function(s){ return s.length });
var a3 = a.map( s => s.length );
剩余参数
如果一个函数的最后一个形参是以 … 为前缀的,则在函数被调用时,该形参会成为一个数组,数组中的元素都是传递给该函数的多出来的实参的值.
//因为theArgs是个数组,所以你可以使用length属性得到剩余参数的个数:
function fun1(...theArgs) {
alert(theArgs.length);
}
fun1(); // 弹出 "0",因为theArgs没有元素
fun1(5); // 弹出 "1",因为theArgs只有一个元素
fun1(5,6,7); // 弹出 "3",因为theArgs有三个元素
组件的生命周期
组件的生命周期有三个主要部分:
- 挂载: 组件被注入DOM。
- 更新: 组件被重新渲染来决定DOM是否应被更新。
- 卸载: 组件从DOM中被移除。
React提供生命周期方法,以便你可以指定钩挂到这个过程上。我们提供了 will 方法,该方法在某事发生前被调用,did方法,在某事发生后被调用。
挂载
getInitialState(): object 在组件挂载前被调用. 有状态组件(Stateful - - components) 应该实现此函数并返回初始state的数据。
componentWillMount() 在挂载发生前被立即调用。
componentDidMount() 在挂载发生后被立即调用。 需要DOM node的初始化应该放在这里。
更新
componentWillReceiveProps(object nextProps) 当挂载的组件接收到新的props时被调用。此方法应该被用于比较this.props 和 nextProps以用于使用this.setState()执行状态转换。
shouldComponentUpdate(object nextProps,object nextState): boolean 当组件决定任何改变是否要更新到DOM时被调用。作为一个优化实现比较this.props 和 nextProps 、this.state 和 nextState ,如果React应该跳过更新,返回false。
componentWillUpdate(object nextProps,object nextState) 在更新发生前被立即调用。你不能在此调用this.setState()。
componentDidUpdate(object prevProps,object prevState) 在更新发生后被立即调用。
卸载
- componentWillUnmount() 在组件被卸载和摧毁后被立即调用。清理应该放在这里。