熱愛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賬號,你可以訪問:https://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 install super-loading --save