您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)編寫vue插件的案例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過來看看吧。
在學(xué)習(xí)之前,先問問自己,為什么要編寫vue的插件。
在一個(gè)項(xiàng)目中,尤其是大型項(xiàng)目,有很多部分需要復(fù)用,比如加載的loading動(dòng)畫,彈出框。如果一個(gè)一個(gè)的引用也稍顯麻煩,而且在一個(gè)vue文件中引用的組件多了,會(huì)顯得代碼臃腫,所以才有了封裝vue插件的需求。
說完需求,就來看看具體實(shí)現(xiàn)。目前我嘗試了兩種不一樣的插件編寫的方法,逐個(gè)介紹。
這是我的項(xiàng)目目錄,大致的結(jié)構(gòu)解釋這樣,盡量簡(jiǎn)單,容易理解。
一個(gè)是loading插件,一個(gè)是toast插件,不同的地方在于:loading插件是作為組件引入使用,而toast插件是直接添加在掛載點(diǎn)里,通過方法改變狀態(tài)調(diào)用的。
目前使用起來是醬紫的:
toast插件
toast文件下有兩個(gè)文件,后綴為vue的文件就是這個(gè)插件的骨架,js文件一個(gè)是將這個(gè)骨架放入Vue全局中,并寫明操作邏輯。
可以看一下toast.vue的內(nèi)容:
<template> <transition name="fade"> <div v-show="show"> {{message}} </div> </transition> </template> <script> export default { data() { return { show: false, message: "" }; } }; </script> <style lang="scss" scoped> .toast { position: fixed; top: 40%; left: 50%; margin-left: -15vw; padding: 2vw; width: 30vw; font-size: 4vw; color: #fff; text-align: center; background-color: rgba(0, 0, 0, 0.8); border-radius: 5vw; z-index: 999; } .fade-enter-active, .fade-leave-active { transition: 0.3s ease-out; } .fade-enter { opacity: 0; transform: scale(1.2); } .fade-leave-to { opacity: 0; transform: scale(0.8); } </style>
這里面主要的內(nèi)容只有兩個(gè),決定是否顯示的show
和顯示什么內(nèi)容的message
。
粗看這里,有沒有發(fā)現(xiàn)什么問題?
這個(gè)文件中并沒有props
屬性,也就是無論是show也好,message也好,就沒有辦法通過父子組件通信的方式進(jìn)行修改,那他們是怎么正確處理的呢。別急,來看他的配置文件。
index.js:
import ToastComponent from './toast.vue' const Toast = {}; // 注冊(cè)Toast Toast.install = function (Vue) { // 生成一個(gè)Vue的子類 // 同時(shí)這個(gè)子類也就是組件 const ToastConstructor = Vue.extend(ToastComponent) // 生成一個(gè)該子類的實(shí)例 const instance = new ToastConstructor(); // 將這個(gè)實(shí)例掛載在我創(chuàng)建的div上 // 并將此div加入全局掛載點(diǎn)內(nèi)部 instance.$mount(document.createElement('div')) document.body.appendChild(instance.$el) // 通過Vue的原型注冊(cè)一個(gè)方法 // 讓所有實(shí)例共享這個(gè)方法 Vue.prototype.$toast = (msg, duration = 2000) => { instance.message = msg; instance.show = true; setTimeout(() => { instance.show = false; }, duration); } } export default Toast
這里的邏輯大致可以分成這么幾步:
創(chuàng)建一個(gè)空對(duì)象,這個(gè)對(duì)象就是日后要使用到的插件的名字。此外,這個(gè)對(duì)象中要有一個(gè)install的函數(shù)。使用vue的extend方法創(chuàng)建一個(gè)插件的構(gòu)造函數(shù)(可以看做創(chuàng)建了一個(gè)vue的子類),實(shí)例化該子類,之后的所有操作都可以通過這個(gè)子類完成。之后再Vue的原型上添加一個(gè)共用的方法。
這里需要著重提的是Vue.extend()
。舉個(gè)例子,我們?nèi)粘J褂胿ue編寫組件是這個(gè)樣子的:
Vue.component('MyComponent',{ template:'<div>這是組件</div>' })
這是全局組件的注冊(cè)方法,但其實(shí)這是一個(gè)語法糖,真正的運(yùn)行過程是這樣的:
let component = Vue.extend({ template:'<div>這是組件</div>' }) Vue.component('MyComponent',component)
Vue.extend會(huì)返回一個(gè)對(duì)象,按照大多數(shù)資料上提及的,也可以說是返回一個(gè)Vue的子類,既然是子類,就沒有辦法直接通過他使用Vue原型上的方法,所以需要new一個(gè)實(shí)例出來使用。
在代碼里console.log(instance)
得出的是這樣的結(jié)果:
可以看到$el:div.toast
也就是toast組件模板的根節(jié)點(diǎn)。
疑惑的是,我不知道為什么要?jiǎng)?chuàng)建一個(gè)空的div節(jié)點(diǎn),并把這個(gè)實(shí)例掛載在上面。我嘗試注釋這段代碼,但是運(yùn)行會(huì)報(bào)錯(cuò)。
查找這個(gè)錯(cuò)誤的原因,貌似是因?yàn)?/p>
document.body.appendChild(instance.$el)
這里面的instance.$el
的問題,那好,我們console下這個(gè)看看。WTF!?。?!結(jié)果居然是undefined
。
那接著
console.log(instance)
和上一張圖片比對(duì)一下,發(fā)現(xiàn)了什么?對(duì),$el消失了,換句話說在我注釋了
instance.$mount(document.createElement('div'))
這句話之后,掛載點(diǎn)也不存在了。接著我試著改了一下這句:
instance.$mount(instance.$el)
$el又神奇的回來了………………
暫時(shí)沒有發(fā)現(xiàn)這種改動(dòng)有什么問題,可以和上面一樣運(yùn)行。但無論如何,這也就是說instance實(shí)例必須掛載在一個(gè)節(jié)點(diǎn)上才能進(jìn)行后續(xù)操作。
之后的代碼就簡(jiǎn)單了,無非是在Vue的原型上添加一個(gè)改變插件狀態(tài)的方法。之后導(dǎo)出這個(gè)對(duì)象。
接下來就是怎么使用的問題了。來看看main.js是怎么寫的:
import Vue from 'vue' import App from './App' // import router from './router' import Toast from './components/taost' Vue.use(Toast) Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ // router, render: h => h(App) }).$mount('#app')
這樣就可以在其他vue文件中直接使用了,像這樣:
// app.vue <template> <div id="app"> <loading duration='2s' :isshow='show'></loading> <!-- <button @click="show = !show">顯示/隱藏loading</button> --> <button @click="toast">顯示taost彈出框</button> </div> </template> <script> export default { name: "app", data() { return { show: false }; }, methods: { toast() { this.$toast("你好"); } } }; </script> <style> #app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
通過在methods中增加一個(gè)方法控制寫在Vue原型上的$toast對(duì)toast組件進(jìn)行操作。
這樣toast組件的編寫過程就結(jié)束了,可以看到一開始gif圖里的效果。
loading插件
經(jīng)過上一個(gè)插件的講解,這一部分就不會(huì)那么細(xì)致了,畢竟大多數(shù)都沒有什么不同,我只指出不一樣的地方。
<template> <div class='wrapper' v-if="isshow"> <div class='loading'> <img src="./loading.gif"> </div> </div> </template> <script> export default { props: { duration: { type: String, default: "1s" //默認(rèn)1s }, isshow: { type: Boolean, default: false } }, data: function() { return {}; } }; </script> <style lang="scss" scoped> </style>
這個(gè)就只是一個(gè)模板,傳入兩個(gè)父組件的數(shù)據(jù)控制顯示效果。
那再來看一下該插件的配置文件:
import LoadingComponent from './loading.vue' let Loading = {}; Loading.install = (Vue) => { Vue.component('loading', LoadingComponent) } export default Loading;
這個(gè)和taoat的插件相比,簡(jiǎn)單了很多,依然是一個(gè)空對(duì)象,里面有一個(gè)install方法,然后在全局注冊(cè)了一個(gè)組件。
比較
那介紹了這兩種不同的插件編寫方法,貌似沒有什么不一樣啊,真的是這樣么?
來看一下完整的main.js和app.vue這兩個(gè)文件:
// main.js import Vue from 'vue' import App from './App' // import router from './router' import Toast from './components/taost' import Loading from './components/loading' Vue.use(Toast) Vue.use(Loading) Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ // router, render: h => h(App) }).$mount('#app') // app.vue <template> <div id="app"> <loading duration='2s' :isshow='show'></loading> <!-- <button @click="show = !show">顯示/隱藏loading</button> --> <button @click="toast">顯示taost彈出框</button> </div> </template> <script> export default { name: "app", data() { return { show: false }; }, methods: { toast() { this.$toast("你好"); } } }; </script> <style> #app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
可以看出來,loading是顯示的寫在app.vue模板里的,而toast并沒有作為一個(gè)組件寫入,僅僅是通過一個(gè)方法控制顯示。
來看一下html結(jié)構(gòu)和vue工具給出的結(jié)構(gòu):
看出來了么,toast插件沒有在掛載點(diǎn)里面,而是獨(dú)立存在的,也就是說當(dāng)執(zhí)行
vue.use(toast)
之后,該插件就是生成好的了,之后的所有操作無非就是顯示或者隱藏的問題了。
感謝各位的閱讀!關(guān)于編寫vue插件的案例分析就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。