自制vue组件通信插件:教你如何用mixin写插件

简书的markdown编译器不好用,看原文


"vue-unicom"的作者:szpoppy,如果觉得对你有用,请一定点个star
这个项目虽然是szpoppy的个人项目,但是在szpoppy公司内是在大面积使用的,一直由szpoppy维护;我个人和szpoppy在一起工作接近一年,经常看他的源代码,从他身上学到非常多。

本文结构:

  • 1.对比VUEX
  • 2.插件已有功能
  • 3.插件如何使用
  • 4.demo演示
  • 5.具体使用方式
  • 6.源码解析,教你如何用mixin写vue插件(一看就会,通俗易懂)

1.对比VUEX

  • ‘vue-unicom’语法直观,使用起来基本没有学习成本;这个插件可以大大简化你的项目
  • 如果说vuex是在视图层组件树之外,创建了一个数据仓库,通过Mutaion修改的话;那么unicom就是在组件之间搭建了一个管道,可以让组件之间通过函数传递、分发数据,并且不像VUEX那样由很多语法
  • VUEX主要做的是状态管理,而‘vue-unicom’纯粹就是做一对一、一对多的组件通信
  • ‘vue-unicom’源代码仅200多行,注释清晰,使用者可以更加深入的了解vue组件如何编写,方便后续创造自己的插件
  • 如果你不确定自己要不要用vuex,就不要用,不需要为了用vuex而用vuex,会用就行,不要搞个中小型项目就直接上vuex,全家桶还是增加了比较多特定语法的;而unicom在性能和实践上完全可以承担起如火车票购票系统规模的应用。
image

2.已有功能

  • 提供任意两个Vue组建之间的通讯问题;
  • 任意一个Vue组件向其他所有组件发送指令;
  • 任意一个Vue组件向某组Vue组件发送指令;
  • 任意一个Vue组件向特定id组件发送消息;
  • 在任意一个Vue组件内获取某组组件列表;
  • 在任意一个Vue组件内获取特定id组件;
  • 发送指令到还没初始化的组件;
  • 发送指令到还没初始化的分组组件;
  • 发送指令到还没初始化的id组件;

3.如何使用

npm install vue-unicom
import VueUnicom from 'vue-unicom'
// 非 cli 也必须 install一下
Vue.use(VueUnicom, {
    // 制定名称, 默认为 unicom
    unicom: 'unicom',
    // 定制分组使用名称 默认为 unicom + 'Name'
    unicomName: 'unicomName',
    // 定制id使用名称 默认为 unicom + 'Id'
    unicomId: 'unicomId'
})

4.demo演示

详情访问这个github的readme地址

// 1. 下载
git clone https://github.com/szpoppy/vue-unicom.git

// 2. 
cd vue-unicom

//3.运行demo,可以直接打开src目录下的index.html(推荐这种更方便的方法)也可以用gulp运行

// 4.‘vue-unicom’源代码在‘/src/lib/unicom.js’

5.具体使用方式

组件编写示例如下,下面进一步详细介绍

    Vue.component('ca', {
    template: '<div><p class="title">text:{{text}}#{{unicomId}}</p><p>msg: {{msg}}</p></div>',
    unicomName: 'a',
    unicom: {
        message: function(sender, text){
            this.msg = text
        }
    },
    data: function(){
        return {
            text: 'component - ca',
            msg: 'a'
        }
    },
    mounted(){
        console.log(' a component  ',this)
    }
})

组件调用示例如下

    <div id="app" class="app">
        <ca unicom-id="a-id1"></ca>
        <ca unicom-id="a-id2"></ca>
        <cb1></cb1>
        <cb2></cb2>
        <cc></cc>
        <hr>
        <cbtn></cbtn>
    </div>

5.1 注册接收指令

{
    // Vue中增加 增加unicom参数
    // 这里的unicom,指 上面传入的参数
    unicom: {
        // instruct1:通讯指令
        // sender:发送指令者($vm)
        // args:指令发出者附带参数
        // 参数如果为对象,是引用类型,如果需要设置,请深度克隆一遍
        instruct1 (sender, ...args) {
            // .... this 为当前组件
        },
        instruct2 (sender, ...args) {

        }
    }
}

5.2 组件内注册分组

{
    // Vue中增加 增加unicomName参数
    // 指定分组 属于 group, 所有实例,都属于这个分组
    unicomName: 'group'
}

5.3 组件加入多个分组

{
    // 组件可以加入多个分组
    unicomName: ['group1', 'group2']
}

5.4 实例中加入组件分组

<!-- 加入group分组 -->
<component unicom-name="group"></component>

5.5 实例中指定 unicomId

<!-- 指定$vm的 id 为 id1 -->
<component unicom-id="id1"></component>

5.6 组件内发送指令

{
    methods:{
        method1 () {
            // 发送 instruct1 指令,参数为 1, 2
            this.$unicom('instruct1', 1, 2)
        }
    }
}

5.7 指令高级用法

instruct1@group (发送到指定分组)

instruct1#id1 (发送到指定组件)

@group (获取指定分组组件)

#id1 (获取指定组件)

5.8 延迟发送指令(一次性指令)

指令使用 ~ 打头

~instruct1 (指令延迟发送,直到包含有instruct1指令的组件出现)

~instruct1@group (指令延迟发送,直到出现分组命名group的组件)

~instruct1#id1 (指令延迟发送,直到出现命名id1的组件)

5.9 组件监听

组件监听使用, 指令使用 ~ 打头, 第二个参数为 callback

~@group (监听分组命名group的组件出现)

~#id1 (监听命名id1的组件出现)

~ (监听任意新出现的组件)

6.简单源码解析

只做基本的源码解析,更加详细可以咨询szpoppy

6.1 用ximin做插件,prototype定义全局函数(插件机制的重点)

建议先阅读vue插件机制https://cn.vuejs.org/v2/guide/plugins.html
拿到源码‘unicom.js’第一步,先用编译器把所有的方法都收起来,除了install函数
接下里我们重点从入口install看起,另外导入插件并app.use的过程中,第一步其实就是调用的install函数

function install(vue, {
        name = 'unicom',
        idName,
        groupName
    } = {}) {
        //简单几行代码判断是否安装过

        // 添加原型方法,全局组件调用
        vue.prototype['$' + name] = unicomQuery

        // unicomIdName = 'unicomId'        id作为唯一标识
        unicomIdName = idName || (name + 'Id')
        // unicomGroupName = 'unicomName'       分组
        unicomGroupName = groupName || (name + 'Name')

        // 全局混入
        vue.mixin({
            props:
            watch:
            beforeCreate(){}
            created(){},
            destroyed(){}
        })

        // 自定义属性合并策略
        let merge = vue.config.optionMergeStrategies
        // 改变了自定义属性unicomName和unicom的合并策略
        merge[name] = merge[unicomGroupName] = function (parentVal, childVal){ 
        //...
        }
    }

其实,按照这样一划分,大家很简单的就能看到这个插件的制作部分大概就分这几块:

6.1.1 prototype

利用vue原型链挂载一个全局的‘$unicom’方法,可以在全局内调用,也可以作为组件内节点click时的方法,click直接发送数据

6.1.2 全局混入mixin

如不了解,建议阅读https://cn.vuejs.org/v2/guide/mixins.html
插件逻辑处理的重点部分:全局混入mixin
props:这个部分非常简单,就是为了让每个组件都能在组件调用时传递变量‘unicom-id’或者‘unicom-name’(一般是静态变量)
watch:这个部分主要就是当组件调用时‘unicom-id’或者‘unicom-name’传递过来的是动态变量对其进行实时监听
beforeCreate:在组件已解析但未加载时,利用‘this.$options’去获取自定义‘unicom’属性,然后在每一个组件内加入事件机制;最后利用Map集合以组件vm作为key,将该组件的分组和通信函数合并的对象作为value存起来
created:在组件已经解析和载入到dom结构之后,从Map集合中获取当前组件的分组和通信函数信息,判断是否有其它组件在当前组件未创建之前给它发送了数据,如果有,响应该延迟发送的数据
destroyed:组件销毁逻辑

6.1.3 自定义属性的混合策略optionMergeStrategies

如不了解,建议阅读vue中的optionMergeStrategies
这个部分看起来简单的几行,其实却是个插件开发过程中比较重点的部分
如何理解这个‘optionMergeStrategies’呢?该组件主要针对自定义option属性的混合;官方解释是:’当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合‘。
肯定很多人还是不明白,其实说实话我也不算明白,但是我简单解释一下:

  1. 这个东西具体的使用你其实可以仔细的看看vuex对这个的使用和‘vue-unicom’中optionMergeStrategies的使用
  2. 官网的这句‘当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合’是很透彻的在讲这个东西的概念
  3. 在‘vue-unicom’插件中optionMergeStrategies有两个用处,一般情况下主要是将‘unicom-id’和‘vue-unicom’从原本数据格式变成数组;但是,如果当前组件或者vue全局被混入了和我们插件自定义option属性同名的变量,默认的合并策略是后面定义的option属性覆盖前面的,但是我们这里对合并策略进行了重写,就可以保证当前组件上所有的‘unicom-id’或者‘vue-unicom’属性都被push到一个数组中并挂载在当前组件上
    简单理解它在当前插件的作用:子组件和上层组件有相同option属性时,让子组件正确合并上层组件的自定义属性

6.2 为什么可以在组件上直接写‘unicomName’、‘unicom’

我们可以很肯定一点:vue本身并没有这两个option属性,甚至很可能很多人也从来没有自己在组件声明时自定义options属性
如果你没有试过,也没有关系,看了本篇文章之后你就知道了
为什么我们要自定义option属性呢?这两个属性的作用很明确,‘unicomName’是做分组声明的,‘unicom’是做通信函数的;然后在mixin的各个声明周期再利用‘this.$options’获取自定义option属性进行进一步的逻辑处理,并声明optionMergeStrategies合并策略

6.3 当前组件的一个亮点

利用map集合以组件vm为单位存储该组件的分组和通信函数
每次存通信函数、分组的时候都会把对应的vm示例存储下来,所以要找通信函数或者对应分组就非常简单

这个组件较我一开始使用已经经过了一次对代码更加直观的改进,个人觉得非常值得大家阅读和使用,开源不易,务必点个star

"vue-unicom"的作者:szpoppy,如果觉得对你有用,请一定点个star,welcom

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,961评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,444评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,009评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,082评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,101评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,271评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,738评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,395评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,539评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,434评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,481评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,160评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,749评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,816评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,038评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,548评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,140评论 2 341

推荐阅读更多精彩内容