自制vue组件通信插件:教你如何用mixin写插件
"vue-unicom"的作者:szpoppy,如果覺(jué)得對(duì)你有用,請(qǐng)一定點(diǎn)個(gè)star
這個(gè)項(xiàng)目雖然是szpoppy的個(gè)人項(xiàng)目,但是在szpoppy公司內(nèi)是在大面積使用的,一直由szpoppy維護(hù);我個(gè)人和szpoppy在一起工作接近一年,經(jīng)常看他的源代碼,從他身上學(xué)到非常多。
本文結(jié)構(gòu):
- 1.對(duì)比VUEX
- 2.插件已有功能
- 3.插件如何使用
- 4.demo演示
- 5.具體使用方式
- 6.源碼解析,教你如何用mixin寫(xiě)vue插件(一看就會(huì),通俗易懂)
1.對(duì)比VUEX
- ‘vue-unicom’語(yǔ)法直觀,使用起來(lái)基本沒(méi)有學(xué)習(xí)成本;這個(gè)插件可以大大簡(jiǎn)化你的項(xiàng)目
- 如果說(shuō)vuex是在視圖層組件樹(shù)之外,創(chuàng)建了一個(gè)數(shù)據(jù)倉(cāng)庫(kù),通過(guò)Mutaion修改的話(huà);那么unicom就是在組件之間搭建了一個(gè)管道,可以讓組件之間通過(guò)函數(shù)傳遞、分發(fā)數(shù)據(jù),并且不像VUEX那樣有很多語(yǔ)法
- VUEX主要做的是狀態(tài)管理,而‘vue-unicom’純粹就是做一對(duì)一、一對(duì)多的組件通信
- ‘vue-unicom’源代碼僅200多行,注釋清晰,使用者可以更加深入的了解vue組件如何編寫(xiě),方便后續(xù)創(chuàng)造自己的插件
- 如果你不確定自己要不要用vuex,就不要用,不需要為了用vuex而用vuex,會(huì)用就行,不要搞個(gè)中小型項(xiàng)目就直接上vuex,全家桶還是增加了比較多特定語(yǔ)法的;而unicom在性能和實(shí)踐上完全可以承擔(dān)起如火車(chē)票購(gòu)票系統(tǒng)規(guī)模的應(yīng)用。
2.已有功能
- 提供任意兩個(gè)Vue組建之間的通訊問(wèn)題;
- 任意一個(gè)Vue組件向其他所有組件發(fā)送指令;
- 任意一個(gè)Vue組件向某組Vue組件發(fā)送指令;
- 任意一個(gè)Vue組件向特定id組件發(fā)送消息;
- 在任意一個(gè)Vue組件內(nèi)獲取某組組件列表;
- 在任意一個(gè)Vue組件內(nèi)獲取特定id組件;
- 發(fā)送指令到還沒(méi)初始化的組件;
- 發(fā)送指令到還沒(méi)初始化的分組組件;
- 發(fā)送指令到還沒(méi)初始化的id組件;
3.如何使用
npm install vue-unicom import VueUnicom from 'vue-unicom' // 非 cli 也必須 install一下 Vue.use(VueUnicom, {// 制定名稱(chēng), 默認(rèn)為 unicomunicom: 'unicom',// 定制分組使用名稱(chēng) 默認(rèn)為 unicom + 'Name'unicomName: 'unicomName',// 定制id使用名稱(chēng) 默認(rèn)為 unicom + 'Id'unicomId: 'unicomId' })4.demo演示
詳情訪(fǎng)問(wèn)這個(gè)github的readme地址
// 1. 下載 git clone https://github.com/szpoppy/vue-unicom.git// 2. cd vue-unicom//3.運(yùn)行demo,可以直接打開(kāi)src目錄下的index.html(推薦這種更方便的方法)也可以用gulp運(yùn)行// 4.‘vue-unicom’源代碼在‘/src/lib/unicom.js’5.具體使用方式
組件編寫(xiě)示例如下,下面進(jìn)一步詳細(xì)介紹
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)} })組件調(diào)用示例如下
<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 注冊(cè)接收指令
{// Vue中增加 增加unicom參數(shù)// 這里的unicom,指 上面?zhèn)魅氲膮?shù)unicom: {// instruct1:通訊指令// sender:發(fā)送指令者($vm)// args:指令發(fā)出者附帶參數(shù)// 參數(shù)如果為對(duì)象,是引用類(lèi)型,如果需要設(shè)置,請(qǐng)深度克隆一遍instruct1 (sender, ...args) {// .... this 為當(dāng)前組件},instruct2 (sender, ...args) {}} }5.2 組件內(nèi)注冊(cè)分組
{// Vue中增加 增加unicomName參數(shù)// 指定分組 屬于 group, 所有實(shí)例,都屬于這個(gè)分組unicomName: 'group' }5.3 組件加入多個(gè)分組
{// 組件可以加入多個(gè)分組unicomName: ['group1', 'group2'] }5.4 實(shí)例中加入組件分組
<!-- 加入group分組 --> <component unicom-name="group"></component>5.5 實(shí)例中指定 unicomId
<!-- 指定$vm的 id 為 id1 --> <component unicom-id="id1"></component>5.6 組件內(nèi)發(fā)送指令
{methods:{method1 () {// 發(fā)送 instruct1 指令,參數(shù)為 1, 2this.$unicom('instruct1', 1, 2)}} }5.7 指令高級(jí)用法
instruct1@group (發(fā)送到指定分組)instruct1#id1 (發(fā)送到指定組件)
@group (獲取指定分組組件)
#id1 (獲取指定組件)
5.8 延遲發(fā)送指令(一次性指令)
指令使用 ~ 打頭
~instruct1 (指令延遲發(fā)送,直到包含有instruct1指令的組件出現(xiàn))~instruct1@group (指令延遲發(fā)送,直到出現(xiàn)分組命名group的組件)
~instruct1#id1 (指令延遲發(fā)送,直到出現(xiàn)命名id1的組件)
5.9 組件監(jiān)聽(tīng)
組件監(jiān)聽(tīng)使用, 指令使用 ~ 打頭, 第二個(gè)參數(shù)為 callback
~@group (監(jiān)聽(tīng)分組命名group的組件出現(xiàn))~#id1 (監(jiān)聽(tīng)命名id1的組件出現(xiàn))
~ (監(jiān)聽(tīng)任意新出現(xiàn)的組件)
6.簡(jiǎn)單源碼解析
只做基本的源碼解析,更加詳細(xì)可以咨詢(xún)szpoppy
6.1 用ximin做插件,prototype定義全局函數(shù)(插件機(jī)制的重點(diǎn))
建議先閱讀vue插件機(jī)制https://cn.vuejs.org/v2/guide/plugins.html
拿到源碼‘unicom.js’第一步,先用編譯器把所有的方法都收起來(lái),除了install函數(shù)
接下里我們重點(diǎn)從入口install看起,另外導(dǎo)入插件并app.use的過(guò)程中,第一步其實(shí)就是調(diào)用的install函數(shù)
其實(shí),按照這樣一劃分,大家很簡(jiǎn)單的就能看到這個(gè)插件的制作部分大概就分這幾塊:
6.1.1 prototype
利用vue原型鏈掛載一個(gè)全局的‘$unicom’方法,可以在全局內(nèi)調(diào)用,也可以作為組件內(nèi)節(jié)點(diǎn)click時(shí)的方法,click直接發(fā)送數(shù)據(jù)
// 組件行級(jí)表達(dá)式使用方式 <button @click="$unicom('message', '通用Send')">發(fā)送指令 message</button> <button @click="$unicom('message@a', 'Send@a')">發(fā)送指令 message@a</button> // 函數(shù)內(nèi)直接調(diào)用使用方式 methods:{sendData(){this.$unicom('message@c', '測(cè)試數(shù)據(jù)')} },6.1.2 全局混入mixin
如不了解,建議閱讀https://cn.vuejs.org/v2/guide/mixins.html
插件邏輯處理的重點(diǎn)部分:全局混入mixin
props:這個(gè)部分非常簡(jiǎn)單,就是為了讓每個(gè)組件都能在組件調(diào)用時(shí)傳遞變量‘unicom-id’或者‘unicom-name’(一般是靜態(tài)變量)
watch:這個(gè)部分主要就是當(dāng)組件調(diào)用時(shí)‘unicom-id’或者‘unicom-name’傳遞過(guò)來(lái)的是動(dòng)態(tài)變量對(duì)其進(jìn)行實(shí)時(shí)監(jiān)聽(tīng)
beforeCreate:在組件已解析但未加載時(shí),利用‘this.$options’去獲取自定義‘unicom’屬性,然后在每一個(gè)組件內(nèi)加入事件機(jī)制;最后利用Map集合以組件vm作為key,將該組件的分組和通信函數(shù)合并的對(duì)象作為value存起來(lái)
created:在組件已經(jīng)解析和載入到dom結(jié)構(gòu)之后,從Map集合中獲取當(dāng)前組件的分組和通信函數(shù)信息,判斷是否有其它組件在當(dāng)前組件未創(chuàng)建之前給它發(fā)送了數(shù)據(jù),如果有,響應(yīng)該延遲發(fā)送的數(shù)據(jù)
destroyed:組件銷(xiāo)毀邏輯
6.1.3 自定義屬性的混合策略optionMergeStrategies
如不了解,建議閱讀vue中的optionMergeStrategies
這個(gè)部分看起來(lái)簡(jiǎn)單的幾行,其實(shí)卻是個(gè)插件開(kāi)發(fā)過(guò)程中比較重點(diǎn)的部分
如何理解這個(gè)‘optionMergeStrategies’呢?該組件主要針對(duì)自定義option屬性的混合;官方解釋是:’當(dāng)組件和混入對(duì)象含有同名選項(xiàng)時(shí),這些選項(xiàng)將以恰當(dāng)?shù)姆绞交旌稀?br />肯定很多人還是不明白,其實(shí)說(shuō)實(shí)話(huà)我也不算明白,但是我簡(jiǎn)單解釋一下:
簡(jiǎn)單理解它在當(dāng)前插件的作用:子組件和上層組件有相同option屬性時(shí),讓子組件正確合并上層組件的自定義屬性
6.2 為什么可以在組件上直接寫(xiě)‘unicomName’、‘unicom’
我們可以很肯定一點(diǎn):vue本身并沒(méi)有這兩個(gè)option屬性,甚至很可能很多人也從來(lái)沒(méi)有自己在組件聲明時(shí)自定義options屬性
如果你沒(méi)有試過(guò),也沒(méi)有關(guān)系,看了本篇文章之后你就知道了
為什么我們要自定義option屬性呢?這兩個(gè)屬性的作用很明確,‘unicomName’是做分組聲明的,‘unicom’是做通信函數(shù)的;然后在mixin的各個(gè)生命周期再利用‘this.$options’獲取自定義option屬性進(jìn)行進(jìn)一步的邏輯處理,并聲明optionMergeStrategies合并策略
6.3 當(dāng)前組件的一個(gè)亮點(diǎn)
利用map集合以組件vm為單位存儲(chǔ)該組件的分組和通信函數(shù)
每次存通信函數(shù)、分組的時(shí)候都會(huì)把對(duì)應(yīng)的vm實(shí)例存儲(chǔ)下來(lái),所以要找通信函數(shù)或者對(duì)應(yīng)分組就非常簡(jiǎn)單
這個(gè)組件較我一開(kāi)始使用已經(jīng)經(jīng)過(guò)了一次對(duì)代碼更加直觀的改進(jìn),個(gè)人覺(jué)得非常值得大家閱讀和使用,開(kāi)源不易,務(wù)必點(diǎn)個(gè)star
"vue-unicom"的作者:szpoppy,如果覺(jué)得對(duì)你有用,請(qǐng)一定點(diǎn)個(gè)star,welcom
總結(jié)
以上是生活随笔為你收集整理的自制vue组件通信插件:教你如何用mixin写插件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Canalys 报告:2023Q2 全球
- 下一篇: 雷柏预热机甲编码主题系列产品线,警戒线