教你輕松解決Vue?Dialog彈窗詬病
摘要
相信用Vue框架多的老哥對彈窗的使用的問題都有一些使用上的詬病,本輪主要闡述針對組件封裝不符合邏輯編寫,如何最小化封裝達成簡化調(diào)用目的。
分析
常規(guī)的Vue前端UI組件如elment-ui、Iview、Ant Design Vue等UI組件庫針對模態(tài)窗的封裝基本都是套式的,MVVM大家基本都在提,從另外一個角度分析Dialog封裝在實際使用上,彈窗過多時漫天的變量如何解決,我們把temlplate中的內(nèi)容理解為表現(xiàn)層,script理解為邏輯層,雖然解決了數(shù)據(jù)的綁定問題,但說實在的,vue的邏輯層和表現(xiàn)層互相穿插使用還是相對存在一些問題,也許你會提Vue也支持Jsx寫法,安裝了插件也能實現(xiàn)React的寫法和效果,此時我以模態(tài)窗的例子來說明一些問題
- elment-ui
- Iview
- Ant Design Vue
大家在實踐過程中,實現(xiàn)這樣一個簡單操作,點擊明細->彈窗表單信息->確定調(diào)用數(shù)據(jù)保存接口 這個過程如一個業(yè)務處理中有很多的編輯彈窗,或者保存邏輯需要連貫性,還有區(qū)分會憑空使得一個處理變得很凌亂復雜。
可以看到一個彈窗,如果擴展3個data變量,兩個方法。如果有10個彈窗,那么也變將會多出來310個屬性和210個方法。 我們針對彈窗的調(diào)用習慣更傾向于layer和react這種隨時取用的寫法
那么問題來了,vue雖然號稱支持jsx寫法如下圖,但卻會失去擁有當前頁面屬性方法共享的部分權(quán)力,本質(zhì)上來說,其實就是函數(shù)式組件乃至于后來都趨向的鉤子函數(shù)或者叫組合式,其本質(zhì)也就是上下文的共享。
優(yōu)化辦法
如果結(jié)合vue特點,要合并屬性和方法,必然要封裝模態(tài)窗為組件,但顯示和確認,并不是一個鏈結(jié)構(gòu),由此就必須實現(xiàn)一個回調(diào),但回調(diào)這種寫法,往往是要在組件中進行一些約定,而且現(xiàn)在在Promise橫行外加aysnc await 去JQ時代鏈式折磨的前提下,簡單來講,異步調(diào)用但采用同步寫法。 如果把Promise比作 "線程" 那我們就需要一個調(diào)度,去控制在點擊 “確認” 時結(jié)束。
- deferred對象就是jQuery的回調(diào)函數(shù)解決方案,$.Deferred 給我提供了思路,也就是把promise對象的reject和resolve開放出來
function generateDeferredPromise() { return (() => { let resolve; let reject; let p = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise: p, reject, resolve }; })(); }
- 完整的模態(tài)窗封裝如下,可以看到我們在show的時候返回了promise對象,在確認的時候觸發(fā)了回調(diào)
<template> <el-dialog :title="title" :visible.sync="drawer"> <slot /> <div slot="footer" class="dialog-footer"> <el-button @click="drawer = false">取 消</el-button> <el-button type="primary" @click="saveData">確 定</el-button> </div> </el-dialog> </template> <script> function generateDeferredPromise() { return (() => { let resolve; let reject; let p = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise: p, reject, resolve }; })(); } export default { name:'modal', props: { title: { type: String, default: undefined, }, handle:{ type:Function, default:(res)=>{}, } }, data() { return { drawer: false, promise:null, } }, mounted() { if(this.handle){ this.handle(this); } }, methods: { show() { this.drawer = true this.promise=new generateDeferredPromise(); return this.promise.promise; }, saveData(){ this.promise.resolve(); this.promise.promise.then(()=>{ this.drawer=false; }) } } } </script> <style> </style>
- 調(diào)用時如下,可以很輕松的變相達成函數(shù)式編程的特點,在調(diào)用時減去了2個屬性和一個方法,10個彈窗由原本的30+20個減少為20。
<modal title="審批/反饋" ref="modal"> <el-descriptions :model="audit" class="margin-top" :column="1" border> <el-descriptions-item label="意見"> <el-radio-group v-model="audit.state"> <el-radio :label="true">通過</el-radio> <el-radio :label="false">不通過</el-radio> </el-radio-group> </el-descriptions-item> <el-descriptions-item label="內(nèi)容"> <el-input type="textarea" v-model="audit.comment"></el-input> </el-descriptions-item> </el-descriptions> </modal> async handleAudit(row) { const { show } = this.$refs["modal"] || {}; show().then(async () => { //保存邏輯處理 }); },
總結(jié)
- 本質(zhì)其實本次分享頁并沒有很多新意,這種引用式的封裝,很多人也早都想到了,只不過感覺針對彈窗這塊的封裝,很多走了極端,要么就追求layer那種寫法兼容習慣,要么干脆還是保留原樣,只做一些特殊處理,屬性還是原樣保留了。
- 至于回調(diào),我之前雖然用過一段,但還是覺得不慎習慣,因為偶然有個共享彈窗存在確認后邏輯不同的問題給我造成了困擾,覺得寫法有點兒變態(tài),因此做了一些嘗試和延展,覺得算是比較良性的一個調(diào)用方式吧。
- 框架性的東西,我詫異的是,理論性的東西,一個比一個探的深,但涉及到便捷性,卻很少有人去探究,乃至于框架性的東西除了UI和風格不同,寫法也大同小異。
到此這篇關(guān)于輕松解決Vue Dialog彈窗詬病的文章就介紹到這了,更多相關(guān)Vue Dialog彈窗問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue的雙向數(shù)據(jù)綁定實現(xiàn)原理解析
這篇文章主要介紹了Vue的雙向數(shù)據(jù)綁定實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-02-02通過vue.extend實現(xiàn)消息提示彈框的方法記錄
這篇文章主要給大家介紹了關(guān)于通過vue.extend實現(xiàn)消息提示彈框的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01