“类 mixin” 指的是 Vue 中的 mixin,Regular 中的 implement

使用 Mixin 的目的

首先我们需要知道为什么会有 mixin 的存在?

  1. 为了扩展对象(组件)的功能

    扩展对象功能的需求是很容易的理解的。比如业务开发时会碰到跨模块传递消息的需求,常用的方法是使用 “发布-订阅模式” 来创建一个全局的EventEmitter。不使用 mixin 时的使用方法如下


    // global/eventEmitter class EventEmitter {
    on(eventName, handle) { } emit(eventName) { }
    } // ComponentA
    import EventEmitter from 'global/eventEmitter'; // 全局的 EventEmitter 对象 class ComponentA {
    constructor() {
    EventEmitter.on('event', () => {});
    }
    } // ComponentB
    import EventEmitter from 'global/eventEmitter'; class ComponentB {
    constructor() {
    EventEmitter.emit('event');
    }
    }

    我们需要在不同的组件中引入 EventEmitter 来使用它

    如果使用 mixin 的话,我们可以这样做


    // eventEmitter mixin
    import EventEmitter from 'global/eventEmitter'; // 全局的 EventEmitter 对象 const eventEmitterMixin = {
    on: (eventName, handle) => {EventEmitter.on(eventName, handle)},
    fire: () => {EventEmitter.emit(eventName)}
    } // Root Component
    Component.mixin(eventEmitterMixin); // ComponentA
    class ComponentA {
    constructor() {
    this.on('event', () => {});
    }
    } // ComponentB
    class ComponentB {
    constructor() {
    this.emit('event');
    }
    }

    这样通过mixin来扩展了组件的功能,是每个组件都可以方便的使用 EventEmitter 的功能

  2. 为了复用代码

    软件开发中的 DRY 原则还是有必要遵守的。过多的重复代码会导致维护上的麻烦,通过 mixin ,我们可以在不同的对象上使用同一份代码来完成相同的功能,减轻我们维护的压力。

复用 VS 扩展

其实这两个没有可比性,但在我们决定是否需要将一个对象通过 mixin 的方式混入到其他对象时就应该考虑这个问题。

原则上 复用 > 扩展

如果一个 mixin 只是为了扩展单个对象的功能,而扩展的功能并不能复用到其他的对象时,就不应该使用 mixin,而是直接写在那个对象上更好。

如果扩展的功能可以被复用的话,那么可以考虑使用 mixin

mixin 的缺点

mixins-considered-harmful 这篇文章已经列举了一些问题,我简单的列举下

  1. mixin 会引入隐性的依赖关系
  2. mixin 会导致命名冲突
  3. mixin 会增加项目的复杂性

如何正确的使用 Mixin

虽然 mixin 有一些缺点,但正确的使用还是可以方便我们的开发

没有不合理的设计模式,只有不合理的使用设计模式

首先我们需要解决混入的 mixin 可能会造成隐性的依赖关系,而形成这种依赖关系多半是 mixin 中的扩展功能依赖了被扩展对象想内部数据,例如:


// 一个数据库查看组件 class DatabaseView {
state = {
database: [{name: 'db1', id: 1, tables: [{name: 'table1', id: 1}]}]
}
} DatabaseView.mixin(viewTabelDetails); // 把查看表详情弹窗作为 mixin 混入
const mixin = {
viewTabelDetails: (dbId, tableId) => {
const db = this.state.database.filter(db => db.id === dbId)[0]; if (db) {
const table = db.tables.filter(table => table.id === tableId)[0]; if (table) {
Model.show(table);
}
}
}
}

上面的例子中,mixin 依赖的 DarabaseView 中的 database 数据。这就导致了如果页面中其他的组件也需要一个查看表详情弹窗的功能,那么这个组件也必须有类似的 database 数据,形成了一个隐性的依赖关系。

避免的方式就是 mixin 对象中的功能不要与被扩展对象发生依赖,而在组件开发中这个依赖多半就是使用了被扩展对象的 state 产生的

至于命名冲突和增加项目的复杂性可以通过其他的方式解决,相比于上面的问题还算简单

总结

  1. mixin 只是用来扩展对象功能的,而且这个扩展功能是可以被复用的,否则你应该直接写在对象里面
  2. 扩展功能的同时,mixin提供的函数不应该依赖被扩展对象的内部数据。因为如果依赖的被扩展对象的内部数据,会使这个 mixin 只能被包含特定数据对象的对象复用,影响 mixin 的复用

个人主观观点

其实我觉得在前端的开发中,我们应该避免使用 mixin 去扩展组件的功能

例如我们完全可以使用函数调用(显性的)去调用 mixin 对象中的方法,而不是一股脑的将 mixin 对象混合到组件中

每次修改使用了 implement 组件都会特别痛苦(这样导入的方法 WebStorm 根本不识别),极大了增加维护的工作量。同时由于有的 mixin 对象依赖的被扩展对象的内部数据,导致想复用的话还得有相同的数据结构(那还复用个锤子啊)

所以,不要用 mixin !!!

更多文章可以查看本人的博客 https://lleohao.github.io

来源:https://segmentfault.com/a/1190000017554489

前端框架中 “类mixin” 模式的思考的更多相关文章

  1. 制作类似ThinkPHP框架中的PATHINFO模式功能(二)

    距离上一次发布的<制作类似ThinkPHP框架中的PATHINFO模式功能>(文章地址:http://www.cnblogs.com/phpstudy2015-6/p/6242700.ht ...

  2. 制作类似ThinkPHP框架中的PATHINFO模式功能

    一.PATHINFO功能简述 搞PHP的都知道ThinkPHP是一个免费开源的轻量级PHP框架,虽说轻量但它的功能却很强大.这也是我接触学习的第一个框架.TP框架中的URL默认模式即是PathInfo ...

  3. Web前端开发中的MCRV模式(转)

    作者: izujian  来源: baiduux 摘要:针对前端开发中基于ajax的复杂页面开发所面临的代码规模大,难以组织和维护,代码复用性.扩展性和适应性差等问题,本文尝试以MVC思想为 基础,结 ...

  4. PythonI/O进阶学习笔记_3.2面向对象编程_python的继承(多继承/super/MRO/抽象基类/mixin模式)

    前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第二篇 继承. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...

  5. 使用appframework前端框架中输入框圆角问题

    目前使用HTML5技术来开发手机跨平台app已经成为了曾经的web开发人员介入移动开发的一条捷径.与此对应也出现了很多新的技术来支撑这样的开发方式,例如国外的phonegap和国内的APPcan等.很 ...

  6. angular中的MVVM模式

    在开始介绍angular原理之前,我们有必要先了解下mvvm模式在angular中运用.虽然在angular社区一直将angular统称为前端MVC框架,同时angular团队也称它为MVW(What ...

  7. 漫谈 GOF 设计模式在 Spring 框架中的实现

    原文地址:梁桂钊的博客 博客地址:http://blog.720ui.com 欢迎关注公众号:「服务端思维」.一群同频者,一起成长,一起精进,打破认知的局限性. 漫谈 GOF 设计模式在 Spring ...

  8. 设计模式在 Spring 框架中的良好应用

    在开始正文之前,请你先思考几个问题: 你项目中有使用哪些 GOF 设计模式 说一说 GOF 23 种设计模式的设计理念 说说 Spring 框架中如何实现设计模式 假设我是面试官问起了你这些面试题,你 ...

  9. day97:MoFang:移动端APP开发准备&移动端项目搭建&APICloud前端框架

    目录 1.移动端开发相关概念 1.APP类型 2.移动端屏幕介绍 3.移动端自适配方案 4.元信息(meta) 2.APP开发准备 1.注册APPCLoud账号 2.下载APP开发编辑器 3.下载AP ...

随机推荐

  1. C开发系列-预处理指令

    简介 OC程序执行过程,在源代码编译成0跟1的二进制文件之前.执行的指令称之为预处理指令. 所有的预处理指令都是以#开头.#import也是预处理指令.预处理指令主要分为三种 宏定义 条件编译 文件包 ...

  2. 目标检测从入门到精通—SPP-Net详细解析(三)

    SPP-Net网络结构分析 Author:Mr. Sun Date:2019.03.18 Loacation: DaLian university of technology 论文名称:<Spa ...

  3. windows API 第13篇 MoveFileEx

    上一篇介绍了MoveFile,这次分析MoveFileEx,它是MoveFile的扩展函数,功能还要更加强大些.先看定义: BOOL WINAPI MoveFileEx( _In_     LPCTS ...

  4. Jmeter环境搭建及目录介绍

    Jmeter环境搭建及目录介绍 运行环境:jmeter是基于java语言的,所有需要准备Java的JDK环境,并添加到环境变量中. 一.环境搭建及配置 1.JMeter的下载: 官网:http://j ...

  5. Win3.2有人用过么

    老牌子的操作系统. 了,有人用过么,我还在用,感觉挺不错的,哈哈哈哈哈.   1.0那一代,画面粗糙,几乎不能算GUI操作系统.   2.0,画面较1.0一代明显改善,可惜的是,手头没货.   3.0 ...

  6. Hibernate-HQL-Criteria-查询优化

    1 查询总结 oid查询-get 对象属性导航查询 HQL Criteria 原生SQL 2 查询-HQL语法 2.1 基础语法 2.2 进阶语法 排序 条件 分页 聚合 投影 多表查询 SQL HQ ...

  7. svn: E170013: Unable to connect to a repository at URL svn: E230001: Server SSL certificate verification

    idea更新项目报E230001: Server SSL certificate verification failed: certificate issued for a different hos ...

  8. TZ_02MyBatis_lazy SqlMapConfig.xml

    Mybatis的延迟加载又称为懒加载 mybatis在一对多的查询中,例如查询一个用户时需要查询这个用户下的所有账户信息,如果一次性的select * from user u left join ac ...

  9. 转var,let,const,js严格模式的详解

    最近看微信公众账号/知乎网上的文章说,现在的前端的人都注重用什么框架,一问原生js感觉都没有用到工作中.用不到的,学这些意义没有.上午我刚面试了一个前端,工作4年吧.最初是北大青鸟培训的,做后端.ne ...

  10. Hackerrank--Ashton and String(后缀数组)

    题目链接 Ashton appeared for a job interview and is asked the following question. Arrange all the distin ...