国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

實例教學如何寫vue插件

2019-11-19 14:49:04
字體:
來源:轉載
供稿:網友

在學習之前,先問問自己,為什么要編寫vue的插件。

在一個項目中,尤其是大型項目,有很多部分需要復用,比如加載的loading動畫,彈出框。如果一個一個的引用也稍顯麻煩,而且在一個vue文件中引用的組件多了,會顯得代碼臃腫,所以才有了封裝vue插件的需求。

說完需求,就來看看具體實現。目前我嘗試了兩種不一樣的插件編寫的方法,逐個介紹。

這是我的項目目錄,大致的結構解釋這樣,盡量簡單,容易理解。

一個是loading插件,一個是toast插件,不同的地方在于:loading插件是作為組件引入使用,而toast插件是直接添加在掛載點里,通過方法改變狀態調用的。

目前使用起來是醬紫的:

toast插件

toast文件下有兩個文件,后綴為vue的文件就是這個插件的骨架,js文件一個是將這個骨架放入Vue全局中,并寫明操作邏輯。

可以看一下toast.vue的內容:

<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>

 

這里面主要的內容只有兩個,決定是否顯示的show和顯示什么內容的message。

粗看這里,有沒有發現什么問題?

這個文件中并沒有props屬性,也就是無論是show也好,message也好,就沒有辦法通過父子組件通信的方式進行修改,那他們是怎么正確處理的呢。別急,來看他的配置文件。

index.js:

import ToastComponent from './toast.vue'const Toast = {};// 注冊ToastToast.install = function (Vue) { // 生成一個Vue的子類 // 同時這個子類也就是組件 const ToastConstructor = Vue.extend(ToastComponent) // 生成一個該子類的實例 const instance = new ToastConstructor(); // 將這個實例掛載在我創建的div上 // 并將此div加入全局掛載點內部 instance.$mount(document.createElement('div')) document.body.appendChild(instance.$el)  // 通過Vue的原型注冊一個方法 // 讓所有實例共享這個方法  Vue.prototype.$toast = (msg, duration = 2000) => {  instance.message = msg;  instance.show = true;  setTimeout(() => {      instance.show = false;  }, duration); }}export default Toast

 

這里的邏輯大致可以分成這么幾步:

創建一個空對象,這個對象就是日后要使用到的插件的名字。此外,這個對象中要有一個install的函數。使用vue的extend方法創建一個插件的構造函數(可以看做創建了一個vue的子類),實例化該子類,之后的所有操作都可以通過這個子類完成。之后再Vue的原型上添加一個共用的方法。

這里需要著重提的是Vue.extend()。舉個例子,我們日常使用vue編寫組件是這個樣子的:

Vue.component('MyComponent',{ template:'<div>這是組件</div>'})

 

這是全局組件的注冊方法,但其實這是一個語法糖,真正的運行過程是這樣的:

let component = Vue.extend({ template:'<div>這是組件</div>'})Vue.component('MyComponent',component)

 

Vue.extend會返回一個對象,按照大多數資料上提及的,也可以說是返回一個Vue的子類,既然是子類,就沒有辦法直接通過他使用Vue原型上的方法,所以需要new一個實例出來使用。

在代碼里console.log(instance)

得出的是這樣的結果:

可以看到$el:div.toast

也就是toast組件模板的根節點。

疑惑的是,我不知道為什么要創建一個空的div節點,并把這個實例掛載在上面。我嘗試注釋這段代碼,但是運行會報錯。

查找這個錯誤的原因,貌似是因為

document.body.appendChild(instance.$el)

 

這里面的instance.$el的問題,那好,我們console下這個看看。WTF!!??!結果居然是undefined。

那接著

console.log(instance)

 

和上一張圖片比對一下,發現了什么?對,$el消失了,換句話說在我注釋了

instance.$mount(document.createElement('div'))

 

這句話之后,掛載點也不存在了。接著我試著改了一下這句:

instance.$mount(instance.$el)

 

$el又神奇的回來了………………

暫時沒有發現這種改動有什么問題,可以和上面一樣運行。但無論如何,這也就是說instance實例必須掛載在一個節點上才能進行后續操作。

之后的代碼就簡單了,無非是在Vue的原型上添加一個改變插件狀態的方法。之后導出這個對象。

接下來就是怎么使用的問題了。來看看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中增加一個方法控制寫在Vue原型上的$toast對toast組件進行操作。

這樣toast組件的編寫過程就結束了,可以看到一開始gif圖里的效果。

loading插件

經過上一個插件的講解,這一部分就不會那么細致了,畢竟大多數都沒有什么不同,我只指出不一樣的地方。

<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" //默認1s }, isshow: {  type: Boolean,  default: false } }, data: function() { return {}; }};</script><style lang="scss" scoped></style>

這個就只是一個模板,傳入兩個父組件的數據控制顯示效果。

那再來看一下該插件的配置文件:

import LoadingComponent from './loading.vue'let Loading = {};Loading.install = (Vue) => { Vue.component('loading', LoadingComponent)}export default Loading;

這個和taoat的插件相比,簡單了很多,依然是一個空對象,里面有一個install方法,然后在全局注冊了一個組件。

比較

那介紹了這兩種不同的插件編寫方法,貌似沒有什么不一樣啊,真的是這樣么?

來看一下完整的main.js和app.vue這兩個文件:

// main.jsimport 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并沒有作為一個組件寫入,僅僅是通過一個方法控制顯示。

來看一下html結構和vue工具給出的結構:

看出來了么,toast插件沒有在掛載點里面,而是獨立存在的,也就是說當執行

vue.use(toast)

之后,該插件就是生成好的了,之后的所有操作無非就是顯示或者隱藏的問題了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 沾益县| 临沧市| 新干县| 信阳市| 阜阳市| 柘城县| 都匀市| 宜阳县| 根河市| 蒲江县| 西安市| 高要市| 仪征市| 隆化县| 繁峙县| 临沧市| 长子县| 宿迁市| 上饶县| 丰县| 东乡| 南宁市| 宝鸡市| 静海县| 普兰店市| 鞍山市| 沈阳市| 工布江达县| 侯马市| 黔西| 津市市| 巴东县| 颍上县| 蓝田县| 柘城县| 仁布县| 阿荣旗| 榆林市| 梅州市| 北宁市| 正宁县|