您好,登錄后才能下訂單哦!
臨近畢業(yè),寫(xiě)了個(gè)簡(jiǎn)單個(gè)人博客,項(xiàng)目地址是點(diǎn)我訪問(wèn)項(xiàng)目地址(順便求star),本篇是系列總結(jié)第一篇。接下來(lái)會(huì)一步一步模仿一個(gè)低配版的Element 的對(duì)話(huà)框和彈框組件。
Vue 單文件組件開(kāi)發(fā)
當(dāng)使用vue-cli初始化一個(gè)項(xiàng)目的時(shí)候,會(huì)發(fā)現(xiàn)src/components文件夾下有一個(gè)HelloWorld.vue文件,這便是單文件組件的基本開(kāi)發(fā)模式。
// 注冊(cè) Vue.component('my-component', { template: '<div>A custom component!</div>' }) // 創(chuàng)建根實(shí)例 new Vue({ el: '#example' })
接下來(lái),開(kāi)始寫(xiě)一個(gè)dialog組件。
Dialog
目標(biāo)對(duì)話(huà)框組件的基本樣式如圖:
根據(jù)目標(biāo)樣式,可以總結(jié)出:
那么,編碼如下:
<template> <div class="ta-dialog__wrapper"> <div class="ta-dialog"> <div class="ta-dialog__header"> <span>{{ title }}</span> <i class="ios-close-empty" @click="handleCancel()"></i> </div> <div class="ta-dialog__body"> <slot></slot> </div> <div class="ta-dialog__footer"> <button @click="handleCancel()">取消</button> <button @click="handleOk()">確定</button> </div> </div> </div> </template> <script> export default { name: 'Dialog', props: { title: { type: String, default: '標(biāo)題' }, }, methods: { handleCancel() { this.$emit('cancel') }, handleOk() { this.$emit('ok') }, }, } </script>
這樣便完成了dialog組件的開(kāi)發(fā),使用方法如下:
<ta-dialog title="彈窗標(biāo)題" @ok="handleOk" @cancel="handleCancel"> <p>我是內(nèi)容</p> </ta-dialog>
這時(shí)候發(fā)現(xiàn)一個(gè)問(wèn)題,通過(guò)使用v-if或者v-show來(lái)控制彈窗的展現(xiàn)時(shí),沒(méi)有動(dòng)畫(huà)?。?!,看上去很生硬。教練,我想加動(dòng)畫(huà),這時(shí)候就該transition組件上場(chǎng)了。使用transition組件結(jié)合css能做出很多效果不錯(cuò)的動(dòng)畫(huà)。接下來(lái)增強(qiáng)dialog組件動(dòng)畫(huà),代碼如下:
<template> <transition name="slide-down"> <div class="ta-dialog__wrapper" v-if="isShow"> // 省略 </div> </transition> </template> <script> export default { data() { return { isShow: true } }, methods: { handleCancel() { this.isShow = false this.$emit('cancel') }, handleOk() { this.isShow = true this.$emit('ok') }, }, } </script>
可以看到transition組件接收了一個(gè)nameprops,那么怎么編寫(xiě)css完成動(dòng)畫(huà)呢?很簡(jiǎn)單的方式,寫(xiě)出兩個(gè)
關(guān)鍵class(css 的 className)樣式即可:
.slide-down-enter-active { animation: dialog-enter ease .3s; } .slide-down-leave-active { animation: dialog-leave ease .5s; } @keyframes dialog-enter { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } @keyframes dialog-leave { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-20px); } }
就是這么簡(jiǎn)單就開(kāi)發(fā)出了效果還不錯(cuò)的動(dòng)效,注意transition組件的name為slide-down,而編寫(xiě)的動(dòng)畫(huà)的關(guān)鍵className為slide-down-enter-active和slide-down-leave-active。
封裝Dialog做MessageBox
Element的MessageBox的使用方法如下:
this.$confirm('此操作將永久刪除該文件, 是否繼續(xù)?', '提示', { confirmButtonText: '確定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.$message({ type: 'success', message: '刪除成功!' }); }).catch(() => { this.$message({ type: 'info', message: '已取消刪除' }); });
看到這段代碼,我的感覺(jué)就是好神奇好神奇好神奇(驚嘆三連)。仔細(xì)看看,這個(gè)組件其實(shí)就是一個(gè)封裝好的dialog,
接下來(lái),我也要封裝一個(gè)這樣的組件。首先,整理下思路:
整理好思路,我就開(kāi)始編碼了:
import Vue from 'vue' import MessgaeBox from './src/index' const Ctur = Vue.extend(MessgaeBox) let instance = null const callback = action => { if (action === 'confirm') { if (instance.showInput) { instance.resolve({ value: instance.inputValue, action }) } else { instance.resolve(action) } } else { instance.reject(action) } instance = null } const showMessageBox = (tip, title, opts) => new Promise((resolve, reject) => { const propsData = { tip, title, ...opts } instance = new Ctur({ propsData }).$mount() instance.reject = reject instance.resolve = resolve instance.callback = callback document.body.appendChild(instance.$el) }) const confirm = (tip, title, opts) => showMessageBox(tip, title, opts) Vue.prototype.$confirm = confirm
至此,可能會(huì)疑惑怎么callback呢,其實(shí)我編寫(xiě)了一個(gè)封裝好的dialog并將其命名為MessageBox,
它的代碼中,有這樣兩個(gè)方法:
onCancel() { this.visible = false this.callback && (this.callback.call(this, 'cancel')) }, onConfirm() { this.visible = false this.callback && (this.callback.call(this, 'confirm')) },
沒(méi)錯(cuò),就是確定和取消時(shí)進(jìn)行callback。我還想說(shuō)一說(shuō)Vue.extend,代碼中引入了MessageBox,
我不是直接new MessageBox而是借助new Ctur,因?yàn)檫@樣可以定義數(shù)據(jù)(不僅僅是props),例如:
instance = new Ctur({ propsData }).$mount()
這時(shí)候,頁(yè)面上其實(shí)是還沒(méi)有MessageBox的,我們需要執(zhí)行:
document.body.appendChild(instance.$el)
如果你直接這樣,你可能會(huì)發(fā)現(xiàn)MessageBox打開(kāi)的時(shí)候沒(méi)有動(dòng)畫(huà),而關(guān)閉的時(shí)候有動(dòng)畫(huà)。解決方法也很簡(jiǎn)單,
appendChild的時(shí)候讓其仍是不可見(jiàn),然后使用類(lèi)這樣的代碼:
Vue.nextTick(() => instance.visible = true)
這樣就有動(dòng)畫(huà)了。
到此,簡(jiǎn)單的Vue組件開(kāi)發(fā)就總結(jié)完了,我寫(xiě)的相關(guān)代碼在地址,https://github.com/mvpzx/elapse/tree/master/be/src/components
免責(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)容。