React组件抽象(一): mixin

13 篇文章 0 订阅
5 篇文章 0 订阅

React组件抽象(一)-Mixin

写业务组件的时候常常会有一些功能反复被不同的组件公用,这时候就需要取出相同部分功能,这个过程涉及组件抽象。抽象方式有许多种,如高阶组件(High-order components)mixin

一、MIxin是什么,为什么要使用Mixin

一些古老的面向对象的语言,如C++,有个很强大但是很危险的功能:多重继承

多重继承

举个例子:
有个程序员写了一本书,那我们可以称这位程序员为作家。
以下例子使用类似JavaScript的语法,因为C++我已经忘记了。

class Person{
    name = "人类"
    writing(){
        // 用笔写字
    }
}
class Writer extends Person{
    name = "作家"
    writing(){
        // 写文章
    }
}
class Coder extends Person{
    name = "程序员"
    writing(){
        //写代码
    }
}

张三恰好是程序员作家,于是继承了两个类

class ZhangSan extends Writer,Coder{
    
}

那么问题来了,当张三writing的时候写代码还是写文章?这就是弊端二义性。如果类数量多了,那将会很难受。当然处理方法是有,主要是麻烦。Java等语言为了规避这么麻烦的事情又要使用继承,出了interface接口。

继承接口

Java允许继承多个接口,如


public class ZhangSan extends Person implements WriterInterface,CoderInterface{
    
}

接口内部不会有实现,子类必须实现interface的方法除非是Abstract。这样就防止了二义性的发生。
然而,其他一些语言引入了其他的方式:mixin

mixin

通过改变prototype的一些属性来给组件注入新的能力。
直接直接举个栗子吧


const mixin = (clazz,plugins) =>{
    Object.entires(clazz).forEach(plugin =>{
        const [key,value] = plugin;
        clazz.prototype[key] = value;
    })
    return clazz;
}
class Zhangsan {
    
}

const mixins = {
    writing(){
        // 写作
    }
}

const WriterZhangSan = mixin(Zhangsan,mixin);

// 是不是很像
//const WriterZhangSan = Object.assign(ZhangSan.prototype,mixin)

二、怎么在React中使用

React.createClass

官方预留接口

React.createClass({
    mixins:[mixins],
    render(){
        return <div>Hello World</div>
    }
})

注意:

  • 多个mixin如果有相同name的实现会报错,并不会后面的覆盖前面的。
  • 定义生命周期如componentDidMount的mixin,并不会覆盖组件方法,而是两个方法都会执行
import createClass from "create-react-class"
const MixinDemo = createClass({
  mixins: [{
    componentDidMount() {
      console.log("mixin")
    }
  }],
  componentDidMount(){
    console.log("Demo")
  },
  render() {
    return <div>123</div>
  }
})
// minxin
// Demo

ES6 class & ES7 decorator :类语修饰器

const mixin = (...mixins) => {
  return target =>{
    mixins.forEach(mixin =>{
      Object.assign(target.prototype,mixin)
    })
    return  target;
  }
}
const didMountSayHello = {
  componentDidMount(){
    console.log("Hello World")
  }
}

@mixin(didMountSayHello)
class MixinDemo extends React.Component{
  render(){
    return <div>2333</div>
  }
}
// Helloworld

举个贴近生产的例子:

每个组件需要国际化语言处理

const languageText = {
    'en_US':user:{
        userName:"User Name"
    },
    'zh_CN':user:{
        userName:"用户名"
    }
}
const injectLanguage = (nameSpace) =>{
    return targetComponent =>{
        targetComponent.prototype.getLanguage = function(){
            return "en_US"
        }
        targetComponent.prototype.getText = function(){
            const currentLanguage = this.getLanguage();
            return languageText[currentLanguage]
        }
        return targetComponent;
    }
}

@languageText("user")
class User extends React.Component{
    render(){
        return <div>{this.props.getText().userName}:<input/></div>
    }
}

三、Mixin的缺点

墙倒众人推,破鼓万人捶。

社区开始不待见这个方式,导致成了“反模式”
Daniel Avramov 发现并提出问题:

  • 破坏原组件的封装

mixin给组件注入新功能的时候,也可能导致加入一些隐藏的状态,维护组件的人难免会踩坑;

  • 命名冲突

引用多个mixin的时候难免会有作者取名雷同,这时候就要花时间去解决这种冲突。

  • 增加复杂性

引入多个mixin的时候尽管你能规避命名和隐藏的功能,但是几个月后或者其他人来看却是难以理解。一个组件内居然实现了这么多功能。

四、替代品

mixin被打入冷宫称为"反模式",必定会有"正模式"来替代它,没错,他就是官方推荐的高阶组件
我们下期再见!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值