理解 React 的工作原理
特点:UI是data决定的,高效的Virtual DOM工作机制。
- UI = f(D);
- 一切皆组件;
- Declarative Programming;
UI = f(D)
常见版本控制工具git/svn采用diff算法时间复杂度为O(n^3)。React采用的diff算法时间复杂度为O(n),无法解决节点移位问题(很少遇到)。
- 动态产生但组建要手动绑定key,key值的引入保证来Virtual DOM的高效工作,但要保证key唯一且稳定。
一切皆组件
希望软件如积木一样,随便拼搭组合。React组件,无状态纯函数
声明式编程(Declarative Programming)vs 命令式编程(Imperative programming)
对比jQuery,声明式只需要关心你想要什么而不必关心具体步骤,这样就避免了版本变动导致API变化但弊端。
JSX 的优势和局限
- 优点:
历史上,html/css/js的分离处于技术上的原因, 按React的哲学,三者合一比较合理。组件内对全局及局部css的处理最为合理。
- 缺点:
JSX需要Bable转译,相关webpack配置棘手。
- 转译示例:
//JSX:
<div>
{
arr.maps(x => <div>x</div>)
}
</div>
//Transpiled JavaScript:
React.createElement(
"div",
null,
arr.maps(x => React.createElement(
"div",
null,
"x"
))
);
- 注意: render里尽可能使用纯函数,避免不纯函数(push,reverse)
props or state
- props:一个组件外部传入的数据;
- state:一个组件内部的状态,组件只能通过setState改变其自身state,尽可能将state推到比较边缘的位置。
- 注意:将父组件props作为子组件state,存在值引用对象的问题
详解 React 组件的生命周期
三种过程:
- mount:
- getDefaultProps
- getInitialState
- componentWillMount
- render
- componentDidMount(只在浏览器上执行)
- update:
- unmount:
常见过程:
-
因state改变引发的update过程:
- shouldComponentUpdate(节省很多不必要的渲染时间,提高React性能)
- componentWillUpdate
- render
- componentDidUpdate
-
因父组件想要render这个组件改变引发的update过程
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
注意: 以render为界,之前的state/props都是没有被改变的,之后的都被改变;React V16有做优化。
如果shouldComponentUpdate返回false,则render不会执行。子组件可能通过connect连接redux,则会有自己但更新过程,但与此无关。
为什么尽量构建无状态组件
毫无疑问,毋庸置疑
用组件封装副作用但功能:
import React from 'react';
export default class HeartBeat extends React.Component {
render() {
return null;
}
componentDidMount() {
this.timer = setInterval(() => {
fetch('/api/v1/heartbeat');
}, 5000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
}
创建高阶组件( HoC , Higher-Order Component)
高阶组件,接受一个参数(至少有一个组件),返回一全新但组件
const HoC = (WrappedComponent) => {
const WrappingComponent = (props) => (
<div className="foo">
<WrappedCompoent {...props} />
</div>
);
return WrappingComponent;
};
继承方式的HoC(不推荐):
const HoC = (WrappedComponent) => {
class WrappingComponent extends WrappendComponent {
render() (
const {user, ...otherProps} = this.props;
this.props = otherProps;
return super.render();
}
}
return WrappingComponent;
};
应用:
组件之间通信
- 父子之间
- 兄弟之间
- 其它之间
通信方式:
- props(父到子,子到父用函数)
- refs(比较笨重,尽可能不用)
- callback(比如promise)
- parent(兄弟组件之间,通过parent)
- global veriable(很拙劣,一般用EventEmmiter)
- redux
FAQ:
-
react如何处理动画呢,也是更新data? 传统的方式(css),更新state
-
immutable在diff中有什么应用场景和优点?
-
如何保持数据的唯一性?减少state有什么好处么?
最好将state集中到一处处理。
-
那么key一般用什么呢?
比如刚才举例的数组下标不行?最好别用,可以尝试利用元素标识符
-
请求回调,setstate之前切换页面,有效解决warning的方式有哪些?
在componentWillUnMount的时候在promise上包一层,加个cancel方法。