继续上一次基础篇, 分享一些关于React的进阶技术
React 进阶部分
- ** context **
- ** setState vs forceUpdate **
- ** Mixins **
- ** HOC **
Components 相关
context
在 React 官方文档上有对 context
的说明:
** context 如何工作? **
首先要在提供 context
的组件中定义 childContextTypes
和 getChildContext
childContextTypes
: 静态属性, 声明传递下去的context
的对象结构, 与propTypes
类似, 但该属性是必须的getChildContext
: 定义在prototype
上的方法, 返回将要传递下去的context
对象,每次状态改变或该组件接收到新的props
的时候该方法将被调用, 其实该方法是在render()
中执行的, 在组件的以下生命周期中能够访问context
componentWillReceiveProps(nextProps,nextContext){...}
shouldComponentUpdate(nextProps,nextState,nextContext){...}
componentWillUpdate(nextProps,nextState,nextContext){...}
componentDidUpdate(previousProps,previousContext){...}
** 使用 context
的缺点 **
- React 中的
context
可能在将来发生变化, 这样依赖它的代码过于脆弱 - React 的
context
是单个子树范围的全局变量, 这样无疑提高了代码的耦合, 在该子树之外也很难重用 - 如果提供
context
的组件的context
发生了变化, 使用context
组件的任何一个父组件使用了shouldComponentUpdate
返回了 false, 则使用者将不会发生更新
引入高阶组件能稍微缓解这些缺点
setState 接受 Function VS Object
为什么要传递函数到 setState
?
React可以将多个 setState()
调用批处理为单个更新以实现性能。
forceUpdate() VS setState()
** setState **
官方关于 setState
的描述
官方关于 forceUpdate
的描述
** 区别 **
forceUpdate()
会跳过 shouldComponentUpdate()
, 不会修改当前的 state
, setState()
与之不同
代码复用
Mixins && HOC
Mixins
现已不推荐
React Mixins
[ _ 以下内容参考本文 _ ]
var LogMixin = {
componentWillMount: function () {
console.log('报告老板, 开始加载!');
},
componentDidMount: function () {
console.log('报告老板, 装载完毕!');
}
};
var AComponent = React.createClass({
mixins: [LogMixin],
render: function () {
return <h1>AComponent</h1>
}
});
var BComponent = React.createClass({
mixins: [LogMixin],
render: function () {
return <h1>BComponent</h1>
}
});
mixin
里的 this
指向组件
组件调用Mixins方法
var Mixin = {
log:function(){
console.log('Mixin log');
}
};
var Component = React.createClass({
mixins: [Mixin],
componentWillMount: function () {
this.log();
},
render: function () {
return <h1>Component</h1>
}
});
生命周期方法 [__ Mixins里的方法并不会覆盖组件的生命周期方法,会在先于组件生命周期方法执行。 __]
var Mixin = {
componentWillMount: function () {
console.log('Mixin Will Mount');
}
};
var Component = React.createClass({
mixins: [Mixin],
componentWillMount: function () {
console.log('Component Will Mount');
},
render: function () {
return <div>Component</div>
}
});
使用多个Mixin [__ 引入的顺序,决定了Mxins里生命周期方法的执行顺序。 __]
var AMixin = {
componentWillMount: function () {
console.log('AMixin Will Mount');
}
};
var BMixin = {
componentWillMount: function () {
console.log('BMixin Will Mount');
}
};
var Component = React.createClass({
mixins: [AMixin,BMixin],
componentWillMount: function () {
console.log('Component Will Mount');
},
render: function () {
return <div>Component</div>
}
});
不允许重复 [__ 除了生命周期方法可以重复以外,其他的方法都不可以重复,否则会报错 __]
不允许 Mixins
内的方法重复, 也不允许 Mixins
内的方法与组件的方法以及组件原型重复
换言之, __ 组件能访问到的方法不能被劫持 __
方法重复案例一
var AMixin = {
log: function () {
console.log('AMixin Log');
}
};
var BMixin = {
log: function () {
console.log('BMixin Log');
}
};
var Component = React.createClass({
mixins: [AMixin,BMixin],
render: function () {
return <div>Component</div>
}
});
方法重复案例二
var Mixin = {
log: function () {
console.log('Mixin Log');
}
};
var Component = React.createClass({
mixins: [Mixin],
log:function(){
console.log('Component Log');
},
render: function () {
return <div>Component</div>
}
});
HOC
如同 高阶函数
, 高阶组件
也是一个函数, 你可以使用 typeof
进行检测, 从定义上来讲它就是一个地地道道的函数, 在 React
家族中我们叫它组件, 它接受一个组件, 返回一个新组件, 注意这里的组件本质上就是函数, 与 React
元素的概念上的区别见上一讲 React基础提升
, 如果非要区分一下组件和函数的话, 那么组件是一种稍微特殊一点的函数, 它是构造函数, 但是 高阶组件
只是一个普通的函数, 从这层意义上讲, 高阶组件
并不是组件, 因为它不是构造函数, 只是一层 包装函数
, 看一下 高阶函数
的大概面貌:
let HOC = BaseComponent => class extends React.Component {
// do something
render() {
return <BaseComponent />
}
};
这里的 HOC 是高阶组件, 并不是它的返回值是高阶组件, 它的返回值只是一个很普通的 React
组件
1
const HOCSomeComponent = SomeComponent => class extends React.Component {
render = x => <SomeComponent { ...this.props } />
}
** 可以做什么? **
const HOCSomeComponent = SomeComponent => class extends React.Component {
render() {
let tel = { mp: '13194099515' };
return <SomeComponent { ...this.props } { ...tel } />;
}
}
const HOCSomeComponent = SomeComponent => class extends React.Component {
render() {
// 还可以传入多个组件
return (
<div>
<SomeComponent { ...this.props } />
</div>
)
}
}
2
const HOCSomeComponent = SomeComponent => class extends SomeComponent {
render = x => super.render()
}
** 还可以做什么? **
条件渲染
const HOCSomeComponent = SomeComponent => class extends SomeComponent {
render() {
if( someValue ) {
return super.render();
} else {
return null;
}
}
}
修改被包裹组件的输出树
const HOCSomeComponent = SomeComponent => class extends SomeComponent {
render() {
const ele = super.render();
let newProps = {};
if(ele[somekey] === someValue) {
newProps = { ... };
}
const props = { ...this.props, ...newProps };
return React.cloneElement(ele, props, ele.props.children);
}
}
const HOCSomeComponent = SomeComponent => class extends SomeComponent {
constructor(props) {
super(props);
this.state = Object.assign({}, this.state, { ... });
}
render() {
return (
div>
{ super.render() }
</div>
)
}
}
...
{
... 不要限制你的思想, HOC 可以做很多...
}