转载来源 感谢分享

Mixins 引入了无形的依赖

  • 应尽量构建无状态组件,Mixin 则反其道而行之
  • Mixin 可能会相互依赖,相互耦合,不利于代码维护
  • 不同的 Mixin 中的方法可能会相互冲突

举个例子

Mixins 有个主要用途是组件从其它数据源订阅数据:

class CommentList extends React.Component {
this.state = {
// "DataSource" 就是全局的数据源
comments: DataSource.getComments()
} componentDidMount() {
// 添加事件处理函数订阅数据
DataSource.addChangeListener(this.handleChange);
} componentWillUnmount() {
// 清除事件处理函数
DataSource.removeChangeListener(this.handleChange);
} handleChange = () => {
// 任何时候数据发生改变就更新组件
this.setState({
comments: DataSource.getComments()
})
} render() {
return (
<div>
{this.state.comments.map((comment) => (
<Comment comment={comment} key={comment.id} />
))}
</div>
)
}
}

当多个组件共用此逻辑时,使用 高阶组件 来优化:

const CommentListWithSubscription = withSubscription(
CommentList,
(DataSource) => DataSource.getComments()
) const BlogPostWithSubscription = withSubscription(
BlogPost,
(DataSource, props) => DataSource.getBlogPost(props.id)
) // 函数接受一个组件参数……
function withSubscription(WrappedComponent, selectData) {
// ……返回另一个新组件……
return class extends React.Component {
this.state = {
data: selectData(DataSource, props)
} componentDidMount() {
// ……注意订阅数据……
DataSource.addChangeListener(this.handleChange)
} componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange)
} handleChange = () => {
this.setState({
data: selectData(DataSource, this.props)
})
} render() {
// ……使用最新的数据渲染组件
// 注意此处将已有的props属性传递给原组件
return <WrappedComponent data={this.state.data} {...this.props} />
}
}
}

高阶组件既不会修改 input 原组件,也不会使用继承复制 input 原组件的行为。相反,高阶组件是通过将原组件包裹(wrapping)在容器组件(container component)里面的方式来组合(composes)使用原组件。高阶组件就是一个没有副作用的纯函数。

抽取状态

说白了就是在无状态组件和其容器组件的关系中,通常让无状态组件不管理自己的状态,状态的管理交给外面的容器组件。

react-redux 的 connect 函数就用来抽取状态,它返回一个高阶组件。

假定你了解 Redux,那么可以看下 connect 的简易实现:

const doNothing = () => ({})

function connect(mapStateToProps=doNothing, mapDispatchToProps=doNothing) {
return function(WarppedComponent) {
class HOC extends React.Component {
this.state = {} componentDidMount() {
this.context.store.subscribe(this.onChange)
} componentWillUmount() {
this.context.store.unsubscribe(this.onChange)
} // HOC 保证 Redux 上 Store 状态变化的时候驱动这个组件的更新
onChange = () => this.setState({}) render() {
const store = this.centext.store
// 执行 getState 得到 Redux Store 状态
// 通过 dispatch 得到传递给 mapDispatchToProps 的 dispatch 方法
const newProps = {
...this.props,
...mapStateToProps(store.getState()),
...mapDispatchToProps(store.dispatch)
} return <WarppedComponent {...newProps} />
}
} // 创建新组件需要利用 Context 功能,所以定义了 types 属性,
// 从 Context 中获取名为 store 的值
HOC.contextTypes = { store.React.PropTypes.object } return HOC
}
}

浅析为什么用高阶组件代替 Mixins的更多相关文章

  1. Mixins 改成使用高阶组件调用

    把组件放在另外一个组件的 render 方法里面, 并且利用了 {...this.props} {...this.state} 这些  JSX 展开属性 对比下2种代码: 原始方式: <!DOC ...

  2. React 高阶组件浅析

    高阶组件的这种写法的诞生来自于社区的实践,目的是解决一些交叉问题(Cross-Cutting Concerns).而最早时候 React 官方给出的解决方案是使用 mixin .而 React 也在官 ...

  3. React文档(二十四)高阶组件

    高阶组件(HOC)是React里的高级技术为了应对重用组件的逻辑.HOCs本质上不是React API的一部分.它是从React的组合性质中显露出来的模式. 具体来说,一个高阶组件就是一个获取一个组件 ...

  4. React高阶组件总结

    在多个不同的组件中需要用到相同的功能,这个解决方法,通常有Mixin和高阶组件. Mixin方法例如: //给所有组件添加一个name属性 var defaultMixin = { getDefaul ...

  5. vue-mixins和vue高阶组件

    我们在开发过程中,因为需求的变更,往往会遇见对现有组件的改造和扩展. 那么我们有什么方法对现有组件进行改造和扩展呢? 常见的我们可以使用mixins方式 下面就让我们来看一下怎么使用mixins方式对 ...

  6. 聊聊React高阶组件(Higher-Order Components)

    使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低 ...

  7. React——高阶组件

    1.在React中higher-order component (HOC)是一种重用组件逻辑的高级技术.HOC不是React API中的一部分.HOC是一个函数,该函数接收一个组件并且返回一个新组件. ...

  8. react 高阶组件的 理解和应用

    高阶组件是什么东西 简单的理解是:一个包装了另一个基础组件的组件.(相对高阶组件来说,我习惯把被包装的组件称为基础组件) 注意:这里说的是包装,可以理解成包裹和组装: 具体的是高阶组件的两种形式吧: ...

  9. React 精要面试题讲解(五) 高阶组件真解

    说明与目录 在学习本章内容之前,最好是具备react中'插槽(children)'及'组合与继承' 这两点的知识积累. 详情请参照React 精要面试题讲解(四) 组合与继承不得不说的秘密. 哦不好意 ...

随机推荐

  1. vue中html、css、js 分离

    在正常的创建和引用vue文件都是html.css.js三者在一起的,这样写起来虽然方便了,但是页面比较大或者代码比较多的情况下,即使使用组件有时代码也比较多,简单来说查找不变不利于编程,大的来说影像优 ...

  2. Oracle 笔记(三)

    Oracle的数据库对象 七大对象:用户.表.约束.序列.视图.同义词和索引 知识点一:用户  -  User  -  账户.管理员-一切对象的宿主 1.创建用户 ???? 2.授权 ???? 授权+ ...

  3. onserverclick

    <button type="button" id="Log_Submit" runat="server" runat="se ...

  4. 关机命令 shutdown

    参考资料:[http://jingyan.baidu.com/article/49ad8bce705f3f5834d8faec.html]

  5. 关于Anaconda3 (64-bit)的一些体验

    最近因为在学习数据分析,所以安装了Anaconda3 (64-bit),最新版,支持py3.7 优点:自带了720个库(官方宣布),自带notebook,spyder.不用自己再去pip各种库了(基本 ...

  6. python 并发编程 异步IO模型

    异步IO(Asynchronous I/O) Linux下的asynchronous IO其实用得不多,从内核2.6版本才开始引入.先看一下它的流程: 用户进程发起read操作之后,立刻就可以开始去做 ...

  7. linux文件过多导致移动失败解决办法

    1. cd /sdzw/data/infogateftp/srcdata/ibp/account_rulelog ls | xargs  -t  -I  {}  mv {} /sdzw/data/in ...

  8. hive排错

    找出错的那个hive实例,看错误日志: 点下面stdout,找Error

  9. 一台 Java 服务器可以跑多少个线程?

    一台Java服务器能跑多少个线程? 这个问题来自一次线上报警如下图,超过了我们的配置阈值. 京东自研UMP监控分析 打出jstack文件,通过IBM Thread and Monitor Dump A ...

  10. 开启linux服务器防火墙

    启用ufwsudo ufw enablesudo ufw default deny运行以上两条命令后,开启了防火墙,并在系统启动时自动开启.关闭所有外部对本机的访问,但本机访问外部正常. 开启和禁用s ...