Vue 外掛編寫與實戰

勞卜發表於2017-08-23

關於

前言

熱愛vue開發的同學肯定知道awesome-vue 這個github地址,裡面包含了數以千計的vue開源外掛,而這些外掛大都來自第三方開發者們,是他們為vue社群提供了大量的技術支援和解決方案。本文立足vue開源的理念,主要為vue開發者講解編寫vue外掛的方法和步驟,通過理論與實踐相結合的方式來加深大家對vue外掛編寫的認識。

vue外掛介紹

1. 外掛與元件

在講解外掛之前,我們首先來了解下vue外掛和元件的關係,在我們的vue專案中我們使用元件的頻率往往會大於外掛,關係如下圖所示:

外掛與元件
外掛與元件

在沒有封裝元件之前,如果不使用第三方外掛,那麼很多情況下我們會編寫幾個常用的元件來提供給頁面使用,如Alert/Loading元件,而你可能需要在很多頁面中引入並且通過components註冊元件,但是像這樣使用率很高的元件一般我們希望全域性註冊後直接就可以在相應頁面使用,因此我們需要將他們封裝成外掛,比如像vux這樣的ui元件庫,即提供了元件功能也提供了某些全域性註冊的外掛。

用一句話簡單概括兩者的關係就是:外掛可以封裝元件,元件可以暴露資料給外掛。

2. 外掛分類

外掛分類
外掛分類

vue外掛的編寫方法一般分為4類,如上圖所示。主要註冊與繫結機制如下:

export default {
    install(Vue, options) {
        Vue.myGlobalMethod = function () {  // 1. 新增全域性方法或屬性,如:  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 上實現
            // 邏輯...
        }
    }
}複製程式碼

上方程式碼使用了es6部分語法列出了4種編寫外掛的方法,而install是註冊外掛主要呼叫的方法,包含了兩個引數(Vue例項和自定義配置屬性options),我們可以將以上程式碼儲存到plugins.js中。

3. 外掛使用

在plugins.js中我們僅僅編寫了一個外掛的空殼子,假如現在需要全域性註冊該外掛,我們可以在入口檔案,比如main.js中註冊:

...

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

Vue.use(MyPlugin);

...複製程式碼

通過全域性方法 Vue.use() 即可使用該外掛,其自動會呼叫install方法。Vue.use會自動阻止註冊相同外掛多次,屆時只會註冊一次該外掛。

vue外掛編寫方法

上述我們提到了編寫外掛的4種方法,接下來我們對其一一進行講解:

1. 新增全域性方法或屬性

export default {
    install(Vue, options) {
        Vue.$myName = '勞卜';
    }
}複製程式碼

在install方法中,我們直接在Vue例項上宣告瞭$myName屬性並進行了賦值,當該外掛註冊後只要存在Vue例項的地方你都可以獲取到Vue.$myName的值,因為其直接繫結在了Vue例項上。

2. 新增全域性資源

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

            // 當繫結元素插入到 DOM 中。
            inserted: function(el, binding, vnode, oldVnode) {

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

            update: function() {},
            componentUpdated: function() {},
            unbind: function() {}
        });
    },
}複製程式碼

新增全域性資源包含了新增全域性的指令/過濾器/過渡等,上方程式碼我們通過Vue.directive()新增了一個全域性指令v-focus,其主要包含了5種方法,其中inserted代表當繫結元素插入到 DOM 中執行,而el.focus()代表聚焦繫結的元素,這樣如果我們在一個input輸入框上繫結該指令就會自動進行focus聚焦。

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

3. 新增全域性mixin方法

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

mixin代表混合的意思,我們可以全域性註冊一個混合,其會影響註冊之後建立的每個 Vue 例項,上方程式碼註冊後會在每個元件例項中新增greetingFn方法,在單檔案元件中可以直接通過this.greetingFn()呼叫。當然如果例項中存在同名方法,則mixin方法中建立的會被覆蓋,同時mixin物件中的鉤子將在元件自身鉤子之前呼叫。

4. 新增例項方法

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

新增例項方法是最常用的一種方法,其直接繫結在vue的原型鏈上,我們可以回想一下 JS 裡的類的概念。例項方法可以在元件內部,通過this.$myMethod來呼叫。

5. 外掛封裝元件

上方4點只講解了外掛自身的4中編寫方法,並沒有涉及元件的內容,如果我們要在元件的基礎上編寫外掛,我們可以使用Vue.extend(component)來進行,可以見下方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()方法建立了一個構造器LoadingPlugin,其次我們再通過new LoadingPlugin()建立了$vm例項,並掛載到一個div元素上。最後我們需要通過document.body.appendChild($vm.$el)將其插入到DOM節點中。

當我們建立了$vm例項後,我們可以訪問該例項的屬性和方法,比如通過$vm.show就可以改變loading元件的show值來控制其顯示隱藏。

最終我們通過Vue.mixin或者Vue.prototype.$loading來全域性新增了$loading事件,其又包含了show和hide兩個方法。我們可以直接在頁面中使用this.$loading.show()來顯示載入,使用this.$loading.hide()來關閉載入。

外掛釋出

外掛編寫完後我們的目的除了本地引用註冊外,可能更希望釋出到線上供他人或其他專案使用,因此我們需要了解外掛釋出的方法。

1. 釋出準備

在釋出外掛前你需要一個npm賬號,你可以訪問:www.npmjs.com/ 進行註冊

2. 釋出命令

npm login
cd 目錄
npm publish複製程式碼

擁有賬號後,你需要在控制檯輸入npm login命令來登入你的賬號,並且輸入郵箱地址。然後開啟你的外掛目錄,允許npm publish釋出。最簡單的一個外掛目錄如下:

3. 釋出目錄

├── lib // 外掛原始碼
│   ├── components // 元件目錄
│   │   └── loading.vue // 元件檔案
│   └── index.js  // 外掛入口檔案
├── index.js // 入口檔案
└── package.json  // 包管理檔案複製程式碼

你可以在專案中安裝剛剛的loading外掛來進行參考,我已經發布至npm:

npm install super-loading --save複製程式碼

當然你也可以訪問github倉庫:github.com/luozhihao/s… 進行下載。

結語

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

相關文章