vue插件編寫與實戰(zhàn)

前言

熱愛vue開發(fā)的同學(xué)肯定知道awesome-vue 這個github地址蜡娶,里面包含了數(shù)以千計的vue開源插件,而這些插件大都來自第三方開發(fā)者們母廷,是他們?yōu)関ue社區(qū)提供了大量的技術(shù)支持和解決方案斑举。本文立足vue開源的理念,主要為vue開發(fā)者講解編寫vue插件的方法和步驟脊奋,通過理論與實踐相結(jié)合的方式來加深大家對vue插件編寫的認(rèn)識熬北。

vue插件介紹

1. 插件與組件

在講解插件之前,我們首先來了解下vue插件和組件的關(guān)系诚隙,在我們的vue項目中我們使用組件的頻率往往會大于插件讶隐,關(guān)系如下圖所示:

插件與組件

在沒有封裝組件之前,如果不使用第三方插件久又,那么很多情況下我們會編寫幾個常用的組件來提供給頁面使用巫延,如Alert/Loading組件,而你可能需要在很多頁面中引入并且通過components注冊組件地消,但是像這樣使用率很高的組件一般我們希望全局注冊后直接就可以在相應(yīng)頁面使用炉峰,因此我們需要將他們封裝成插件,比如像vux這樣的ui組件庫脉执,即提供了組件功能也提供了某些全局注冊的插件讲冠。

用一句話簡單概括兩者的關(guān)系就是:插件可以封裝組件,組件可以暴露數(shù)據(jù)給插件适瓦。

2. 插件分類

插件分類

vue插件的編寫方法一般分為4類竿开,如上圖所示。主要注冊與綁定機制如下:

export default {
    install(Vue, options) {
        Vue.myGlobalMethod = function () {  // 1. 添加全局方法或?qū)傩圆N酰?  vue-custom-element
            // 邏輯...
        }

        Vue.directive('my-directive', {  // 2. 添加全局資源:指令/過濾器/過渡等否彩,如 vue-touch
            bind (el, binding, vnode, oldVnode) {
                // 邏輯...
            }
            ...
        })
    
        Vue.mixin({
            created: function () {  // 3. 通過全局 mixin方法添加一些組件選項,如: vuex
                // 邏輯...
            }
            ...
        })    
    
        Vue.prototype.$myMethod = function (options) {  // 4. 添加實例方法嗦随,通過把它們添加到 Vue.prototype 上實現(xiàn)
            // 邏輯...
        }
    }
}

上方代碼使用了es6部分語法列出了4種編寫插件的方法列荔,而install是注冊插件主要調(diào)用的方法敬尺,包含了兩個參數(shù)(Vue實例和自定義配置屬性options),我們可以將以上代碼存儲到plugins.js中贴浙。

3. 插件使用

在plugins.js中我們僅僅編寫了一個插件的空殼子砂吞,假如現(xiàn)在需要全局注冊該插件,我們可以在入口文件崎溃,比如main.js中注冊:

...

import Vue from 'vue'
import MyPlugin from './plugins/plugins.js'

Vue.use(MyPlugin);

...

通過全局方法 Vue.use() 即可使用該插件蜻直,其自動會調(diào)用install方法。Vue.use會自動阻止注冊相同插件多次袁串,屆時只會注冊一次該插件概而。

vue插件編寫方法

上述我們提到了編寫插件的4種方法,接下來我們對其一一進(jìn)行講解:

1. 添加全局方法或?qū)傩?/h3>
export default {
    install(Vue, options) {
        Vue.$myName = '勞卜';
    }
}

在install方法中囱修,我們直接在Vue實例上聲明了$myName屬性并進(jìn)行了賦值赎瑰,當(dāng)該插件注冊后只要存在Vue實例的地方你都可以獲取到Vue.$myName的值,因為其直接綁定在了Vue實例上破镰。

2. 添加全局資源

export default {
    install(Vue, options) {
        Vue.directive('focus', {
            bind: function() {},

            // 當(dāng)綁定元素插入到 DOM 中餐曼。
            inserted: function(el, binding, vnode, oldVnode) {

                // 聚焦元素
                el.focus();
            },

            update: function() {},
            componentUpdated: function() {},
            unbind: function() {}
        });
    },
}

添加全局資源包含了添加全局的指令/過濾器/過渡等,上方代碼我們通過Vue.directive()添加了一個全局指令v-focus鲜漩,其主要包含了5種方法晋辆,其中inserted代表當(dāng)綁定元素插入到 DOM 中執(zhí)行,而el.focus()代表聚焦綁定的元素宇整,這樣如果我們在一個input輸入框上綁定該指令就會自動進(jìn)行focus聚焦。

其他directive提供的方法及用途可以參考:vue自定義指令

3. 添加全局mixin方法

export default {
    install(Vue, options) {
        Vue.mixin({
            methods: {
                greetingFn() {
                    console.log('greeting');
                }
            }
        });
    },
}

mixin代表混合的意思芋膘,我們可以全局注冊一個混合鳞青,其會影響注冊之后創(chuàng)建的每個 Vue 實例,上方代碼注冊后會在每個組件實例中添加greetingFn方法为朋,在單文件組件中可以直接通過this.greetingFn()調(diào)用臂拓。當(dāng)然如果實例中存在同名方法,則mixin方法中創(chuàng)建的會被覆蓋习寸,同時mixin對象中的鉤子將在組件自身鉤子之前調(diào)用胶惰。

4. 添加實例方法

export default {
    install(Vue, options) {
        Vue.prototype.$myName = '勞卜';
        Vue.prototype.showMyName = value => {
            console.log(value);
        };
    },
}

添加實例方法是最常用的一種方法,其直接綁定在vue的原型鏈上霞溪,我們可以回想一下 JS 里的類的概念孵滞。實例方法可以在組件內(nèi)部,通過this.$myMethod來調(diào)用鸯匹。

5. 插件封裝組件

上方4點只講解了插件自身的4中編寫方法坊饶,并沒有涉及組件的內(nèi)容,如果我們要在組件的基礎(chǔ)上編寫插件殴蓬,我們可以使用Vue.extend(component)來進(jìn)行匿级,可以見下方loading插件實例。

loading插件

<!-- loading.vue組件 -->
<template>
    <div class="loading-box" v-show="show">
        <div class="loading-mask"></div>
        <div class="loading-content">
            <div class="animate">
            </div>
            <div class="text">{{text}}</div>
        </div>
    </div>
</template>

<script>
export default {
    props: {
        show: Boolean,
        text: {
          type: String,
          default: '正在加載中...'
        },
    }
}
</script>

以上是一個loading.vue組件,省略了樣式部分痘绎,在沒有封裝插件之前津函,我們只能通過import引入并注冊到components對象中才能在頁面中使用,如:

<template>
    <div>
        <loading :show="true"></loading>
    </div>
</template>
<script>
import Loading from './loading.vue'

export default {
    ...
    
    components: {
        Loading
    }
    
    ...
}
</script>

下面我們便來封裝一下該組件:

// loading.js
import LoadingComponent from '../components/loading.vue'

let $vm

export default {
    install(Vue, options) {
        if (!$vm) {
            const LoadingPlugin = Vue.extend(LoadingComponent);

            $vm = new LoadingPlugin({
                el: document.createElement('div')
            });

            document.body.appendChild($vm.$el);
        }

        $vm.show = false;

        let loading = {
            show(text) {
                $vm.show = true;

                $vm.text = text;
            },
            hide() {
                $vm.show = false;
            }
        };

        if (!Vue.$loading) {
            Vue.$loading = loading;
        }

        // Vue.prototype.$loading = Vue.$loading;

        Vue.mixin({
            created() {
                this.$loading = Vue.$loading;
            }
        })
    }
}

以上我們新建一個loading.js文件孤页,引入我們的loading.vue組件尔苦,然后通過Vue.extend()方法創(chuàng)建了一個構(gòu)造器LoadingPlugin,其次我們再通過new LoadingPlugin()創(chuàng)建了$vm實例散庶,并掛載到一個div元素上蕉堰。最后我們需要通過document.body.appendChild($vm.$el)將其插入到DOM節(jié)點中。

當(dāng)我們創(chuàng)建了$vm實例后悲龟,我們可以訪問該實例的屬性和方法屋讶,比如通過$vm.show就可以改變loading組件的show值來控制其顯示隱藏。

最終我們通過Vue.mixin或者Vue.prototype.$loading來全局添加了$loading事件须教,其又包含了show和hide兩個方法皿渗。我們可以直接在頁面中使用this.$loading.show()來顯示加載,使用this.$loading.hide()來關(guān)閉加載轻腺。

插件發(fā)布

插件編寫完后我們的目的除了本地引用注冊外乐疆,可能更希望發(fā)布到線上供他人或其他項目使用,因此我們需要了解插件發(fā)布的方法贬养。

1. 發(fā)布準(zhǔn)備

在發(fā)布插件前你需要一個npm賬號挤土,你可以訪問:https://www.npmjs.com/ 進(jìn)行注冊

2. 發(fā)布命令

npm login
cd 目錄
npm publish

擁有賬號后,你需要在控制臺輸入npm login命令來登錄你的賬號误算,并且輸入郵箱地址仰美。然后打開你的插件目錄,允許npm publish發(fā)布儿礼。最簡單的一個插件目錄如下:

3. 發(fā)布目錄

├── lib // 插件源碼
│   ├── components // 組件目錄
│   │   └── loading.vue // 組件文件
│   └── index.js  // 插件入口文件
├── index.js // 入口文件
└── package.json  // 包管理文件

你可以在項目中安裝剛剛的loading插件來進(jìn)行參考咖杂,我已經(jīng)發(fā)布至npm:

npm install super-loading --save

當(dāng)然你也可以訪問github倉庫:https://github.com/luozhihao/super-loading 進(jìn)行下載。

結(jié)語

本文的最終目的并不是教大家如何去編寫一個loading插件蚊夫,而是幫助大家了解在編寫插件的過程中所使用的技巧和方法诉字,只有掌握了技巧和方法才能寫出各種各樣的插件,正所謂水到自然渠成知纷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壤圃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子琅轧,更是在濱河造成了極大的恐慌埃唯,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹰晨,死亡現(xiàn)場離奇詭異墨叛,居然都是意外死亡止毕,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門漠趁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扁凛,“玉大人,你說我怎么就攤上這事闯传〗鞒” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵甥绿,是天一觀的道長字币。 經(jīng)常有香客問我,道長共缕,這世上最難降的妖魔是什么洗出? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮图谷,結(jié)果婚禮上翩活,老公的妹妹穿的比我還像新娘。我一直安慰自己便贵,他們只是感情好菠镇,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著承璃,像睡著了一般利耍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盔粹,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天隘梨,我揣著相機與錄音,去河邊找鬼玻佩。 笑死,一個胖子當(dāng)著我的面吹牛席楚,可吹牛的內(nèi)容都是我干的咬崔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼烦秩,長吁一口氣:“原來是場噩夢啊……” “哼垮斯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起只祠,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤兜蠕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后抛寝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體熊杨,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡曙旭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了晶府。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桂躏。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖川陆,靈堂內(nèi)的尸體忽然破棺而出剂习,到底是詐尸還是另有隱情,我是刑警寧澤较沪,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布鳞绕,位于F島的核電站,受9級特大地震影響尸曼,放射性物質(zhì)發(fā)生泄漏们何。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一骡苞、第九天 我趴在偏房一處隱蔽的房頂上張望垂蜗。 院中可真熱鬧,春花似錦解幽、人聲如沸贴见。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽片部。三九已至,卻和暖如春霜定,著一層夾襖步出監(jiān)牢的瞬間档悠,已是汗流浹背藏雏。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工隆箩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舆乔。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓磨德,卻偏偏與公主長得像缘回,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子典挑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載 :OpenDiggawesome-github-vue 是由OpenDigg整理并維護的Vue相關(guān)開源項目庫...
    果汁密碼閱讀 23,117評論 8 124
  • 來源:github.com Vue.js開源項目速查表:https://www.ctolib.com/cheats...
    zhangtaiwei閱讀 11,614評論 1 159
  • 20170714化解計劃趕不上變化:收集徹底 外事篩選 減少日程 批量處理 第一種酥宴,假性變化。原本就存在您觉,因收集不...
    阿小杜閱讀 159評論 0 0
  • 你對于讀書的看法是什么拙寡? 我挺喜歡聽別人講故事,有時候聽他們說我自己沒有發(fā)生過的事情琳水,就感覺這世界如此神奇肆糕,還會有...
    郁鎖清秋閱讀 276評論 0 0
  • 百年前的陽光嫵媚 是斯人明眸垂淚 白發(fā)千年詩句唱之不盡 靈魂幻化絲竹林 色彩生靈無聲愚蠢 鳴叫悲啼 落花水邊戲樹影...
    錦書性空山閱讀 244評論 0 1