自制vue組件通訊插件:教你如何用mixin寫插件

"vue-unicom"的做者:szpoppy,若是以爲對你有用,請必定點個star
這個項目雖然是szpoppy的我的項目,可是在szpoppy公司內是在大面積使用的,一直由szpoppy維護;我我的和szpoppy在一塊兒工做接近一年,常常看他的源代碼,從他身上學到很是多。javascript

本文結構:html

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

1.對比VUEX

  • ‘vue-unicom’語法直觀,使用起來基本沒有學習成本;這個插件能夠大大簡化你的項目
  • 若是說vuex是在視圖層組件樹以外,建立了一個數據倉庫,經過Mutaion修改的話;那麼unicom就是在組件之間搭建了一個管道,可讓組件之間經過函數傳遞、分發數據,而且不像VUEX那樣有不少語法
  • VUEX主要作的是狀態管理,而‘vue-unicom’純粹就是作一對1、一對多的組件通訊
  • ‘vue-unicom’源代碼僅200多行,註釋清晰,使用者能夠更加深刻的瞭解vue組件如何編寫,方便後續創造本身的插件
  • 若是你不肯定本身要不要用vuex,就不要用,不須要爲了用vuex而用vuex,會用就行,不要搞箇中小型項目就直接上vuex,全家桶仍是增長了比較多特定語法的;而unicom在性能和實踐上徹底能夠承擔起如火車票購票系統規模的應用。

clipboard.png

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地址vue

// 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.具體使用方式

組件編寫示例以下,下面進一步詳細介紹java

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)
    }
})

組件調用示例以下git

<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 (發送到指定組件)github

@group (獲取指定分組組件)vuex

#id1 (獲取指定組件)npm

5.8 延遲發送指令(一次性指令)

指令使用 ~ 打頭gulp

~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直接發送數據

// 組件行級表達式使用方式
<button @click="$unicom('message', '通用Send')">發送指令 message</button>     
<button @click="$unicom('message@a', 'Send@a')">發送指令 message@a</button>
// 函數內直接調用使用方式
methods:{
      sendData(){
          this.$unicom('message@c', '測試數據')
      }
},
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

相關文章
相關標籤/搜索