您好,登錄后才能下訂單哦!
前言
在平時的開發(fā)過程中,我們總是先寫好一個組件,然后在需要的頁面中用 import 引入即可,但如果是下面這種類型的組件呢👇
上面這種類型的浮層提示有一個很大的特點,就是使用頻率特別高,幾乎每個頁面都會用到它,于是乎我們就要在每個頁面中去引入該組件,并且在每個頁面都得通過一個變量來控制它的顯隱,這顯然不是我們想要的🙅。。。那我們想要的是什么樣呢🤔?用過一些 UI 框架的同學(xué)們應(yīng)該知道有這樣一種用法:
this.$toast({ duration: 3000, content: '這是一條消息提示' });
沒錯,就是這么簡單的一句話就萬事大吉了(就是用 js 調(diào)用組件而已啦🧐)。那這種效果究竟是怎么實現(xiàn)的呢?今天就讓我們來(手把手🤝 )一探究竟吧!
前置知識
不知道小伙伴們有沒有用過 Vue.extend() 這個東東,反正我是很少碰過,印象不深,所以這里我們先來短暫了解一下 Vue.extend() 主要是用來干嘛的。先來個官方說明(不多的,堅持下):
沒怎么看懂?😴沒關(guān)系,不重要,你只要記?。由僭S理解)以下用法即可:
// 導(dǎo)入以往的普通組件 import Main from './main.vue'; // 用 Vue.extend 創(chuàng)建組件的模板(構(gòu)造函數(shù)) let mainConstructor = Vue.extend(Main); // 實例化組件 let instance = new mainConstructor(); // 掛載到相應(yīng)的元素上 instance.$mount('#app');
不知道你看懂沒有,上面的 Vue.extend(Main) 就是一個基于 main.vue 的組件模板(構(gòu)造函數(shù)),instance 是實例化的組件,$mount() 是手動掛載的意思。其中 Vue.extend() 和 $mount() 就是我們通過 js 調(diào)用、渲染并掛載組件的精髓所在,相當(dāng)于早前的 createElement 和 appendChild,有異曲同工之效。這個點需要我們好好熟悉一下,所以你可以先停下來屢屢思路🤔。
補(bǔ)充一下🤐:$mount() 里面如果沒有參數(shù),說明組件只是渲染了但還沒有掛載到頁面上,如果有正確的(元素)參數(shù)則直接掛載到元素下面。
寫一個 toast 組件
js 調(diào)用歸調(diào)用,最原始的組件還是要有的,只是我們不通過 import 來引入到頁面中而已。ok,我們就以最開始的那個 toast 圖片來簡單寫一下這個 vue 組件(message 和 alert 也是一樣的)。這里就直接上代碼啦,畢竟它的結(jié)構(gòu)簡單到爆了,也不是本章節(jié)的重點:
<!-- main.vue --> <template> <div class="toast"> <p>服務(wù)器錯誤,請稍后重試</p> </div> </template> <script> export default { name: "Toast", mounted() { setTimeout(() => { // 3s 后通過父級移除子元素的方式來移除該組件 this.$el.parentNode.removeChild(this.$el); }, 3000); } }; </script> <style lang="scss" scoped> .toast { display: flex; align-items: center; justify-content: center; position: fixed; top: 0; bottom: 0; left: 0; right: 0; color: #fff; z-index: 9999; background: transparent; > p { padding: 12px 22px; font-size: 18px; border-radius: 4px; background: rgba(17, 17, 17, 0.7); } } </style>
上面的內(nèi)容想必大家應(yīng)該都能看懂,所以這里就直接講下面的重點了。
寫一個 main.js
我們在 main.vue 的同級目錄下新建一個 main.js 文件。我們先瞟一眼文件內(nèi)容(也不多,已經(jīng)是個最簡版了)👇:
// main.js import Vue from "vue"; // 引入 Vue 是因為要用到 Vue.extend() 這個方法 import Main from "./main.vue"; // 引入剛才的 toast 組件 let ToastConstructor = Vue.extend(Main); // 這個在前面的前置知識內(nèi)容里面有講到 let instance; const Toast = function() { instance = new ToastConstructor().$mount(); // 渲染組件 document.body.appendChild(instance.$el); // 掛載到 body 下 }; export default Toast; 。
上面的代碼暴露了一個 Toast 函數(shù)。為什么要暴露一個函數(shù)呢?原因很簡單:你想想,我們最終是不是要根據(jù) this.$toast() 來調(diào)用一個組件,說白了,通過 js 調(diào)用,本質(zhì)就是調(diào)用一個 函數(shù)。也就是說 this.$toast() 就是執(zhí)行了上面代碼中導(dǎo)出的 export default Toast,也就是執(zhí)行了 Toast 函數(shù)(const Toast = function() {}),所以當(dāng)我們調(diào)用 this.$toast() 的時候其實就是執(zhí)行了 Toast() 函數(shù)。而 Toast() 函數(shù)只做了一件事情:就是通過手動掛載的方式把組件掛載到 body 下面。
補(bǔ)充一下🤐:一般來說我們常見的是 $mount("#app"),也就是把組件掛載到 #app 下面,<router-view /> 也包含在 #app 中,但是我們這種 toast 提示是放在 body 下面的,也就是說它不受 #app 和 <router-view /> 的管控,所以當(dāng)我們切換頁面(路由)的時候,這個 toast 組件是不會跟著立馬消失的,這點要注意哦😯。
這里順便給個組件的目錄結(jié)構(gòu),如下圖所示:
開始調(diào)用
調(diào)用方式很簡單,首先我們在入口文件 main.js(和上面不是同一個😢) 里加上兩行代碼,這樣我們就能在需要的地方直接用 js 調(diào)用它了,如下圖所示:
然后在頁面中測試一下,就像下面這樣子:
運行一下代碼:
嗯,挺好,小有成就的 feel 👏👏👏。
支持可傳參數(shù)
別急,我們好像還漏了點什么🤔。。。對了,現(xiàn)在還不支持傳參呢,直接調(diào)用 this.$toast() 就只能顯示————服務(wù)器錯誤,請稍后重試(這下全都是后端的鍋了😊)。但我們可是個有追求的前端,不能局限于此,所以現(xiàn)在讓我們來嘗試增加下兩個可配置參數(shù),這里拿 duration 和 content 舉個栗子🌰。
首先我們要修改 main.vue 組件里面的內(nèi)容(其實沒啥大變化),就像下面這樣:
<!-- main.vue 可配置版 --> <template> <div class="toast"> <p>{{ content }}</p> </div> </template> <script> // 主要就改了 data export default { name: "Toast", data() { return { content: "", duration: 3000 }; }, mounted() { setTimeout(() => { this.$el.parentNode.removeChild(this.$el); }, this.duration); } }; </script>
上面的代碼應(yīng)該算是淺顯易懂了,接下來我們看下 main.js 里面改了啥:
// main.js 可配置版 import Vue from "vue"; import Main from "./main.vue"; let ToastConstructor = Vue.extend(Main); let instance; const Toast = function(options = {}) { // 就改了這里,加了個 options 參數(shù) instance = new ToastConstructor({ data: options // 這里的 data 會傳到 main.vue 組件中的 data 中,當(dāng)然也可以寫在 props 里 }); document.body.appendChild(instance.$mount().$el); }; export default Toast;
其實 main.js 也沒多大變化,就是在函數(shù)里面加了個參數(shù)。要注意的是 new ToastConstructor({ data: options }) 中的 data 就是 main.vue 組件中的 data,不是隨隨便便取的字段名,傳入的 options 會和組件中的 data 合并(Vue 的功勞)。
em。。。是的,就這么簡單,現(xiàn)在讓我們繼續(xù)來調(diào)用一下它:
<script> export default { methods: { showToast() { this.$toast({ content: "哈哈哈哈,消失的賊快", duration: 500 }); } } }; </script>
運行一下就可以看到:
當(dāng)然,這還沒完,我們繼續(xù)添加個小功能點🙄。。。
支持 this.$toast.error()
這里我們打算支持 this.$toast.error() 和 this.$toast.success() 這兩種方式,所以我們第一步還是要先去修改一下 main.vue 文件的內(nèi)容(主要就是根據(jù) type 值來修改組件的樣式),就像下面這樣:
<!--main.vue--> <template> <div class="toast" :class="type ? `toast--${type}` : ''"> <p>{{ content }}</p> </div> </template> <script> export default { ... data() { return { type: "", content: "", duration: 3000 }; }, ... }; </script> <style lang="scss" scoped> .toast { ... &--error p { background: rgba(255, 0, 0, 0.5); } &--success p { background: rgba(0, 255, 0, 0.5); } } </style>
其次,this.$toast.error() 其實就等價于 Toast.error(),所以我們現(xiàn)在的目的就是要給 Toast 函數(shù)擴(kuò)充方法,也比較簡單,就先看代碼再解釋吧:
// main.js const Toast = function(options = {}) { ... }; // 以下就是在 Toast 函數(shù)中拓展 ["success", "error"] 這兩個方法 ["success", "error"].forEach(type => { Toast[type] = options => { options.type = type; return Toast(options); }; }); export default Toast;
我們可以看到 Toast.error() 和 Toast.success() 最終還是調(diào)用 Toast(options) 這個函數(shù),只不過在調(diào)用之前需要多做一步處理,就是將 ["success", "error"] 作為一個 type 參數(shù)給合并進(jìn) options 里面再傳遞,僅此而已😬。
那就試試效果吧:
<script> export default { methods: { showToast() { this.$toast({ content: "這是正常的" }); }, showErrorToast() { this.$toast.error({ content: "竟然失敗了" }); }, showSuccessToast() { this.$toast.success({ content: "居然成功了" }); } } }; </script>
大贊無疆,大。贊。。無。。。疆。。。。。👍
結(jié)語
至此,一個通過 js 調(diào)用的簡單 toast 組件就搞定啦,短短的幾行代碼還是挺考驗 js 功底的💪。當(dāng)然這只是個超簡易版的 demo,顯然不夠完善和健壯,所以我們可以在此基礎(chǔ)上擴(kuò)充一下,比如當(dāng) duration <= 0 的時候,我們讓這個 toast 一直顯示,然后擴(kuò)展一個 close 方法來關(guān)閉等等之類的。不過還是那句老話,實踐才是檢驗真理的唯一標(biāo)準(zhǔn)。紙上得來終覺淺,絕知此事要躬行。step by step, day day up ! 🎉 🎉 🎉
以上所述是小編給大家介紹的vue this.$toast()用法詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對億速云網(wǎng)站的支持!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。