這篇文章給大家分享的是有關(guān)Vue如何實(shí)現(xiàn)彈窗Modal的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。
10余年的宜春網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營銷型網(wǎng)站的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整宜春建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“宜春網(wǎng)站設(shè)計(jì)”,“宜春網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
Vue作為最近最炙手可熱的前端框架,其簡(jiǎn)單的入門方式和功能強(qiáng)大的API是其優(yōu)點(diǎn)。而同時(shí)因?yàn)槠銩PI的多樣性和豐富性,所以他的很多開發(fā)方式就和一切基于組件的React不同,如果沒有對(duì)Vue的API(有一些甚至文檔都沒提到)有一個(gè)全面的了解,那么在開發(fā)和設(shè)計(jì)一個(gè)組件的時(shí)候有可能就會(huì)繞一個(gè)大圈子,所以我非常推薦各位在學(xué)習(xí)Vue的時(shí)候先要對(duì)Vue核心的所有API都有一個(gè)了解。這篇文章我會(huì)從實(shí)踐出發(fā),遇到一些知識(shí)點(diǎn)會(huì)順帶總結(jié)一下。文章很長,一次看不完可以先收藏,如果你剛?cè)腴Tvue,那么相信這篇文章對(duì)你以后的提升絕對(duì)有幫助
進(jìn)入正題,我相信不論什么項(xiàng)目幾乎都會(huì)有一個(gè)必不可少的功能,就是用戶操作反饋、或者提醒.像這樣(簡(jiǎn)單的一個(gè)demo)
其實(shí)在vue的中大型項(xiàng)目中,這些類似的小功能會(huì)更加豐富以及嚴(yán)謹(jǐn),而在以Vue作為核心框架的前端項(xiàng)目中,因?yàn)閂ue本身是一個(gè)組件化和虛擬Dom的框架,要實(shí)現(xiàn)一個(gè)通知組件的展示當(dāng)然是非常簡(jiǎn)單的。但因?yàn)橥ㄖM件的使用特性,直接在模板當(dāng)中書寫組件并通過v-show或者props控制通知組件的顯示顯然是非常不方便的并且這樣意味著你的代碼結(jié)構(gòu)要變,當(dāng)各種各樣的彈層變多的時(shí)候,我們都將其掛載到APP或者一個(gè)組件下顯然不太合理,而且如果要在action或者其他非組件場(chǎng)景中要用到通知,那么純組件模式的用法也無法實(shí)現(xiàn)。那么有沒有辦法即用到Vue組件化特性方便得實(shí)現(xiàn)一個(gè)通知組件的展現(xiàn),那么我們可否用一個(gè)方法來控制彈層組件的顯示和隱藏呢?
目標(biāo)一
實(shí)現(xiàn)一個(gè)簡(jiǎn)單的反饋通知,可以通過方法在組件內(nèi)直接調(diào)用。比如Vue.$confirm({...obj})
首先,我們來實(shí)現(xiàn)通知組件,相信這個(gè)大部分人都能寫出來一個(gè)像模像樣的組件,不啰嗦,直接上代碼
{{ msg }}
在這里需要注意,我們定義了一個(gè)close方法,但內(nèi)容是空的,雖然在模板上有用到,但是似乎沒什么意義,在后面我們要擴(kuò)展組件的時(shí)候我會(huì)講到為什么要這么做。
創(chuàng)建完這個(gè)組件之后,我們就可以在模板中使用了
實(shí)現(xiàn)通過方法調(diào)用該通知組件
其實(shí)在實(shí)現(xiàn)通過方法調(diào)用之前,我們需要擴(kuò)展一下這個(gè)組件,因?yàn)閮H僅這些屬性,并不夠我們使用。在使用方法調(diào)用的時(shí)候,我們需要考慮一下幾個(gè)問題:
顯示反饋的定位
組件的出現(xiàn)和自動(dòng)消失控制
連續(xù)多次調(diào)用通知方法,如何排版多個(gè)通知
在這個(gè)前提下,我們需要擴(kuò)展該組件,但是擴(kuò)展的這些屬性不能直接放在原組件內(nèi),因?yàn)檫@些可能會(huì)影響組件在模板內(nèi)的使用,那怎么辦呢?這時(shí)候我們就要用到Vue里面非常好用的一個(gè)API,extend,通過他去繼承原組件的屬性并擴(kuò)展他。
來看代碼
import Notifier from './Notifier.vue' function install(Vue) { Vue.notifier = Vue.prototype.notifier = { success, fail, info, warn } } function open(type, msg) { let UiNotifier = Vue.extend(Notifier) let vm = new UiNotifier({ propsData: { type, msg }, methods: { close: function () { let dialog = this.$el dialog.addEventListener('animationend', () => { document.body.removeChild(dialog) this.$destroy() }) dialog.className = `${this.type} eqc-notifier close` dialog = null } } }).$mount() document.body.appendChild(vm.$el) } function success(msg) { open('success', msg) } function fail(msg) { open('fail', msg) } function info(msg) { open('info', msg) } function warn(msg) { open('warn', msg) } Vue.use(install) export default install
可以看到close方法在這里被實(shí)現(xiàn)了,那么為什么要在原組件上面加上那些方法的定義呢?因?yàn)樾枰谀0迳辖壎?,而模板是無法extend的,只能覆蓋,如果要覆蓋重新實(shí)現(xiàn),那擴(kuò)展的意義就不是很大了。其實(shí)這里只是一個(gè)消息彈窗組件,是可以在模板中就被實(shí)現(xiàn),還有插件怎么注入,大家都可以自己抉擇。
同時(shí)在使用extend的時(shí)候要注意:
方法和屬性的定義是直接覆蓋的
生命周期方法類似余mixin,會(huì)合并,也就是原組件和繼承之后的組件都會(huì)被調(diào)用,原組件先調(diào)用
首先通過 let UiNotifier = Vue.extend(Notifier),我們得到了一個(gè)類似于Vue的子類,接著就可以通過new UiNotifier({...options})的方式去創(chuàng)建Vue的實(shí)例了,同時(shí)通過該方式創(chuàng)建的實(shí)例,會(huì)有組件定義里面的所有屬性。
在創(chuàng)建實(shí)例之后,vm.$mount()手動(dòng)將組件掛載到DOM上面,這樣我們可以不依賴Vue組件樹來輸出DOM片段,達(dá)到自由顯示通知的效果。
擴(kuò)展:
說一下$mount,我們也許很多項(xiàng)目的主文件是這樣的
new Vue({ router, store, el: '#app', render: h => h(App) })
其實(shí)el與$mount在使用效果上沒有任何區(qū)別,都是為了將實(shí)例化后的vue掛載到指定的dom元素中。如果在實(shí)例化vue的時(shí)候指定el,則該vue將會(huì)渲染在此el對(duì)應(yīng)的dom中,反之,若沒有指定el,則vue實(shí)例會(huì)處于一種“未掛載”的狀態(tài),此時(shí)可以通過$mount來手動(dòng)執(zhí)行掛載。值得注意的是如果$mount沒有提供參數(shù),模板將被渲染為文檔之外的的元素,并且你必須使用原生DOM API把它插入文檔中,所以我上面寫的你應(yīng)該明白了吧!
這是$mount的一個(gè)源碼片段,其實(shí)$mount的方法支持傳入2個(gè)參數(shù)的,第一個(gè)是 el,它表示掛載的元素,可以是字符串,也可以是 DOM 對(duì)象,如果是字符串在瀏覽器環(huán)境下會(huì)調(diào)用 query 方法轉(zhuǎn)換成 DOM 對(duì)象的。第二個(gè)參數(shù)是和服務(wù)端渲染相關(guān),在瀏覽器環(huán)境下不需要傳第二個(gè)參數(shù)。
好了,我們現(xiàn)在其實(shí)就可以在組件中:
this.notifier[state](msg)來調(diào)用了,是不是很方便?
進(jìn)階
我們剛才實(shí)現(xiàn)了在Vue中通過方法來進(jìn)行用戶反饋的提醒,再增加一個(gè)難度:
我們vue項(xiàng)目中應(yīng)該也遇到過這種情況,彈出一個(gè)對(duì)話框或是選擇框?不但要求用方法彈出,并且能接收到對(duì)話框交互所返回的結(jié)果。
這里就不詳細(xì)的分析了直接上代碼說(之前的代碼,用render來寫的組件,懶得改了,直接拿來用...),先創(chuàng)建一個(gè)對(duì)話框組件---Confirm.vue
然后創(chuàng)建confirm.js
'use strict' import Confirm from './Confirm.vue' const confirmConstructor = Vue.extend(Confirm) const ConfirmViewStyle = config => { const confirmInstance = new confirmConstructor({ data() { return { config } } }) confirmInstance.vm = confirmInstance.$mount() confirmInstance.dom = confirmInstance.vm.$el document.body.appendChild(confirmInstance.dom) } const close = () => { let dom = document.querySelector('body .modelServe-container') dom && dom.remove() Vue.prototype.$receive = null } const closeConfirm = () => { let dom = document.getElementById('__confirm') dom && dom.remove() Vue.prototype.$confirm = null } function install(Vue) { Vue.prototype.modelServe = { confirm: (obj) => { return new Promise(resolve => { Vue.prototype.$confirm = (data) => { resolve(data) closeConfirm() } ConfirmViewStyle(obj) }) } } Vue.prototype.$dismiss = close Vue.prototype.$cancel = closeConfirm } Vue.use(install) export default install
思路很簡(jiǎn)單,在我們創(chuàng)建的時(shí)候同時(shí)返回一個(gè)promise,同時(shí)將resolve通行證暴露給vue的一個(gè)全局方法也就是將控制權(quán)暴露給外部,這樣我們就可以向這樣,我上面的confiram.vue是直接把取消綁定成了$cancel,把確定綁定成了$confirm,所以點(diǎn)擊確定會(huì)進(jìn)入full,也就是.then中,當(dāng)然你也可以傳參數(shù)
this.modelServe.confirm({ msg: '返回后數(shù)據(jù)不會(huì)被保存,確認(rèn)?', ifBtn: true }).then(_ => { this.goBack() }).catch()
寫的有點(diǎn)多,其實(shí)還可以擴(kuò)展出好多技巧,比如模態(tài)框中傳一個(gè)完整的組件,并展示出來,簡(jiǎn)單地寫一下,其實(shí)只需改動(dòng)一點(diǎn)
import Model from './Model.vue' const modelConstructor = Vue.extend(Model) const modelViewStyle = (obj) => { let component = obj.component const modelViewInstance = new modelConstructor({ data() { return { disabledClick: obj.stopClick // 是否禁止點(diǎn)擊遮罩層關(guān)閉 } } }) let app = document.getElementById('container') modelViewInstance.vm = modelViewInstance.$mount() modelViewInstance.dom = modelViewInstance.vm.$el app.appendChild(modelViewInstance.dom) new Vue({ el: '#__model__', mixins: [component], data() { return { serveObj: obj.obj } } }) } ... Vue.prototype.modelServe = { open: (obj) => { return new Promise(resolve => { modelViewStyle(obj, resolve) Vue.prototype.$receive = (data) => { resolve(data) close() } }) } }
調(diào)用:
sendCallBack() { this.modelServe.open({ component: AddCallback, stopClick: true }).then(data => if (data === 1) { this.addInit() } else { this.goBack() } })
這里我們用了mixins,最后最后再簡(jiǎn)單地介紹一下mixins,extend,extends的區(qū)別
**- Vue.extend使用基礎(chǔ) Vue 構(gòu)造器,創(chuàng)建一個(gè)“子類”。參數(shù)是一個(gè)包含組件選項(xiàng)的對(duì)象。
mixins 選項(xiàng)接受一個(gè)混入對(duì)象的數(shù)組。這些混入實(shí)例對(duì)象可以像正常的實(shí)例對(duì)象一樣包含選項(xiàng),他們將在 Vue.extend() 里最終選擇使用相同的選項(xiàng)合并邏輯合并。舉例:如果你的混入包含一個(gè)鉤子而創(chuàng)建組件本身也有一個(gè),兩個(gè)函數(shù)將被調(diào)用。Mixin 鉤子按照傳入順序依次調(diào)用,并在調(diào)用組件自身的鉤子之前被調(diào)用。
注意(data混入組件數(shù)據(jù)優(yōu)先鉤子函數(shù)將混合為一個(gè)數(shù)組,混入對(duì)象的鉤子將在組件自身鉤子之前調(diào)用,值為對(duì)象的選項(xiàng),例如 methods, components 和 directives,將被混合為同一個(gè)對(duì)象。兩個(gè)對(duì)象鍵名沖突時(shí),取組件對(duì)象的鍵值對(duì)。)
extends 允許聲明擴(kuò)展另一個(gè)組件(可以是一個(gè)簡(jiǎn)單的選項(xiàng)對(duì)象或構(gòu)造函數(shù)),而無需使用 Vue.extend。這主要是為了便于擴(kuò)展單文件組件。這和 mixins 類似。**
概括
extend用于創(chuàng)建vue實(shí)例 mixins可以混入多個(gè)mixin,extends只能繼承一個(gè) mixins類似于面向切面的編程(AOP),extends類似于面向?qū)ο蟮木幊? 優(yōu)先級(jí)Vue.extend>extends>mixins
感謝各位的閱讀!關(guān)于“Vue如何實(shí)現(xiàn)彈窗Modal”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!