React系列-Mixin、HOC、Render Props(上)
React系列-轻松学会Hooks(中)
React系列-自定义Hooks很简单(下)
用了一段时间的
Hooks
,结合几篇文档,整理些笔记????
在讲react-hooks
之前,我们来捋捋react状态逻辑复用
相关知识点,这会帮助你理解hooks
React 里,组件是代码复用的基本单元
,基于组合的组件复用机制相当优雅。而对于更细粒度的逻辑(状态逻辑、行为逻辑等)
,复用起来却不那么容易
,所以我们是通过分析以下几种模式
来解决我们状态逻辑复用
问题
Mixin(混入)
Mixin设计模式
Mixin模式就是一些提供能够被一个或者一组子类简单
继承功能的类
,意在重用其功能
很多开源库提供了Mixin的实现
,比如Underscore的_.extend方法
动手实现Minxin方法
const mixin = function (target, mixins) {
const newObj = target;
newObj.prototype = Object.create(target.prototype);
for (let prop in mixins) {
if (mixins.hasOwnProperty(prop)) {
newObj.prototype[prop] = mixins[prop];
}
}
return newObj;
}
const Person = {
run: () => {
console.log('I can run');
}
};
const Son = function () {
console.log('hello world');
};
const User = mixin(Son, Person);
const vnues = new User(); // 'hello world'
vnues.run(); // 'I can run'
❗️可以看到使用mixin方法将任意对象的任意方法扩展到目标对象上
,也就是说采用Mixin方式可以复用状态逻辑、行为逻辑等
React中的Mixin
Mixin 方案的出现源自一种 OOP 直觉
,虽然 React 本身有些函数式味道
,但为了迎合用户习惯,早期只提供了React.createClass() API
来定义组件:
// 定义Mixin
var Mixin1 = {
getMessage: function() {
return 'hello react';
}
};
var Mixin2 = {
componentDidMount: function() {
console.log('Mixin2.componentDidMount()');
}
};
// 用Mixin来增强现有组件
var MyComponent = React.createClass({
mixins: [Mixin1, Mixin2],
render: function() {
return <div>{this.getMessage()}</div>;
}
});
Mixin带来的缺陷
Mixins 引入了隐式的依赖关系(Mixins introduce implicit dependencies)
你可能会写一个有状态的组件,然后你的同事可能添加一个读取这个组件state的mixin。几个月之后,你可能希望将该state移动到父组件,以便与其兄弟组件共享。你会记得更新这个mixin来
读取props而不是state吗
?如果此时,其它组件也在使用这个mixin呢?
var RowMixin = {
renderHeader: function() {
return (
<div className='row-header'>
<h1>
{this.getHeaderText()} // 隐式依赖
</h1>
</div>
);
}
};
var UserRow = React.createClass({
mixins: [RowMixin], // 混入renderHeader方法
getHeaderText: function() {
return this.props.user.fullName;
},
render: function() {
return (
<div>
{this.renderHeader()}
<h2>{this.props.user.biography}</h2>
</div>
)
}
});
隐式依赖导致依赖关系不透明,维护成本和理解成本迅速攀升:
难以快速理解组件行为,需要全盘了解所有依赖 Mixin 的扩展行为,及其之间的相互影响
组价自身的方法和state字段不敢轻易删改,因为难以确定有没有 Mixin 依赖它
Mixin 也难以维护,因为 Mixin 逻辑最后会被
打平合并到一起
,很难搞清楚一个 Mixin 的输入输出
Mixins 引起名称冲突(Mixins cause name clashes)
你在该Mixin定义了getDefaultProps, 另外一个Mixin又定义了同样的名称getDefaultProps,
造成了冲突
。
var DefaultNameMixin = {
// 名称冲突
getDefaultProps: function () {
return {name: "Lizie"};
}
};
var DefaultFoodMixin = {
// 名称冲突
getDefaultProps: function () {
return {food: "Pancakes"};
}
};
var ComponentTwo = React.createClass({
mixins: [DefaultNameMixin, DefaultFoodMixin],
render: function () {