熱愛vue開發的同窗確定知道awesome-vue 這個github地址,裏面包含了數以千計的vue開源插件,而這些插件大都來自第三方開發者們,是他們爲vue社區提供了大量的技術支持和解決方案。本文立足vue開源的理念,主要爲vue開發者講解編寫vue插件的方法和步驟,經過理論與實踐相結合的方式來加深你們對vue插件編寫的認識。javascript
在講解插件以前,咱們首先來了解下vue插件和組件的關係,在咱們的vue項目中咱們使用組件的頻率每每會大於插件,關係以下圖所示:html
在沒有封裝組件以前,若是不使用第三方插件,那麼不少狀況下咱們會編寫幾個經常使用的組件來提供給頁面使用,如Alert/Loading組件,而你可能須要在不少頁面中引入而且經過components註冊組件,可是像這樣使用率很高的組件通常咱們但願全局註冊後直接就能夠在相應頁面使用,所以咱們須要將他們封裝成插件,好比像vux這樣的ui組件庫,即提供了組件功能也提供了某些全局註冊的插件。前端
用一句話簡單歸納二者的關係就是:插件能夠封裝組件,組件能夠暴露數據給插件。vue
vue插件的編寫方法通常分爲4類,如上圖所示。主要註冊與綁定機制以下:java
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中。node
在plugins.js中咱們僅僅編寫了一個插件的空殼子,假如如今須要全局註冊該插件,咱們能夠在入口文件,好比main.js中註冊:git
...
import Vue from 'vue'
import MyPlugin from './plugins/plugins.js'
Vue.use(MyPlugin);
...複製代碼
經過全局方法 Vue.use() 便可使用該插件,其自動會調用install方法。Vue.use會自動阻止註冊相同插件屢次,屆時只會註冊一次該插件。es6
上述咱們提到了編寫插件的4種方法,接下來咱們對其一一進行講解:github
export default {
install(Vue, options) {
Vue.$myName = '勞卜';
}
}複製代碼
在install方法中,咱們直接在Vue實例上聲明瞭$myName屬性並進行了賦值,當該插件註冊後只要存在Vue實例的地方你均可以獲取到Vue.$myName的值,由於其直接綁定在了Vue實例上。vuex
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自定義指令
export default {
install(Vue, options) {
Vue.mixin({
methods: {
greetingFn() {
console.log('greeting');
}
}
});
},
}複製代碼
mixin表明混合的意思,咱們能夠全局註冊一個混合,其會影響註冊以後建立的每一個 Vue 實例,上方代碼註冊後會在每一個組件實例中添加greetingFn方法,在單文件組件中能夠直接經過this.greetingFn()調用。固然若是實例中存在同名方法,則mixin方法中建立的會被覆蓋,同時mixin對象中的鉤子將在組件自身鉤子以前調用。
export default {
install(Vue, options) {
Vue.prototype.$myName = '勞卜';
Vue.prototype.showMyName = value => {
console.log(value);
};
},
}複製代碼
添加實例方法是最經常使用的一種方法,其直接綁定在vue的原型鏈上,咱們能夠回想一下 JS 裏的類的概念。實例方法能夠在組件內部,經過this.$myMethod來調用。
上方4點只講解了插件自身的4中編寫方法,並無涉及組件的內容,若是咱們要在組件的基礎上編寫插件,咱們可使用Vue.extend(component)來進行,能夠見下方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()來關閉加載。
插件編寫完後咱們的目的除了本地引用註冊外,可能更但願發佈到線上供他人或其餘項目使用,所以咱們須要瞭解插件發佈的方法。
在發佈插件前你須要一個npm帳號,你能夠訪問:www.npmjs.com/ 進行註冊
npm login
cd 目錄
npm publish複製代碼
擁有帳號後,你須要在控制檯輸入npm login命令來登陸你的帳號,而且輸入郵箱地址。而後打開你的插件目錄,容許npm publish發佈。最簡單的一個插件目錄以下:
├── lib // 插件源碼
│ ├── components // 組件目錄
│ │ └── loading.vue // 組件文件
│ └── index.js // 插件入口文件
├── index.js // 入口文件
└── package.json // 包管理文件複製代碼
你能夠在項目中安裝剛剛的loading插件來進行參考,我已經發布至npm:
npm install super-loading --save複製代碼
固然你也能夠訪問github倉庫:github.com/luozhihao/s… 進行下載。
本文的最終目的並非教你們如何去編寫一個loading插件,而是幫助你們瞭解在編寫插件的過程當中所使用的技巧和方法,只有掌握了技巧和方法才能寫出各類各樣的插件,正所謂水到天然渠成。