Vue基礎:使用Vue.extend()實現自定義確認框


問題背景

前端交互中經常使用確認框。在刪除、修改等操作時,調用后端接口之前,先跳出彈框顯示提示信息,提示用戶確認,避免用戶誤操作。
項目中全局引入了Element UI,提供了一套模態對話框組件,用於消息提示、確認消息、提交內容,使用起來也非常簡便。
(什么是“模態”?可將其理解為:特定條件觸發之后產生的)

以下來自於element官網文檔:

如果你完整引入了 Element,它會為Vue.prototype添加如下全局方法: $msgbox, $alert, $confirm $prompt。因此在Vue instance中可以采用本頁面中的方式調用 MessageBox。

代碼范例:

 
 this.$confirm("此操作將永久刪除該文件, 是否繼續?", "提示", {
                    confirmButtonText: "確定",
                    cancelButtonText: "取消",
                    type: "warning"
                })
                    .then(() => {
                        this.$message({ type: "success", message: "刪除成功!" });
                    })
                    .catch(() => {
                        this.$message({ type: "info", message: "已取消刪除" });
                    });

Element允許復寫樣式,如果全局都需要,則可以進行寫在全局自定義樣式單中,覆蓋掉原有樣式。
當Element提供的默認組件不能滿足需求時,需要思考一下如何實現?

實現嘗試

在單組件內部實現確認框

在組件內定義一個對話框,使用時將dialog顯示為可見,點擊確認時調用方法,點擊取消/關閉時將dialog設置為不可見。
在當前頁面只需要一個確認框的時候,dialog的標題、內容、確認時調用的方法(@click = "handler")都可以寫死。

  • 怎么修改對話框內容?
    當頁面上有多個不同方法均需要對話框確認,那么el-dialog對應的數據是變動的,使用 v-model指令綁定一個confirmDialog對象,在觸發對話框時,實時修改該對話框所顯示的內容,以及按鈕對應的方法。
<el-dialog width="600px" :title="confirmDialog.title" :visible.sync="confirmDialog.show">
                <span>{{ confirmDialog.message }}</span>
                <div slot="footer" class="dialog-footer">
                    <el-button @click="confirmDialog.show = false">
                        取 消
                    </el-button>
                    <el-button type="primary" @click="confirmDialog.handler">
                        確 定
                    </el-button>
                </div>
            </el-dialog>

<el-button @click = ""></el-button>

script中方法:

           deleteFile() {
                this.confirmDialog.title = "刪除";
                this.confirmDialog.message = "確認刪除文件嗎?";
                this.confirmDialog.handler = this.doDeleteFile;
                this.confirmDialog.show = true;
            },
            doDeleteFile() {
                // 刪除文件方法
            }
  • 公有部分抽取
    在上述實現中,我們使用多個不同方法去操作同一對象,並且每個操作都需要兩個方法實現,第一個方法用來修改confirmDialog的值,第二個方法用來監聽確認按鈕的點擊事件,執行操作。
    很容易得出,第一個方法是每個操作都類似的,可以復用的,彈窗HTML代碼和樣式代碼也是共用的,我們將公有的部分獨立成組件,就避免了重復工作。

如何抽取?

由上一節,我們容易得出,需要抽取的是確認框的DOM,樣式,以及數據對象。

為什么使用extend

上一章總結了子組件如何抽取,並介紹了在父組件中如何使用子組件,使用方法為:
在父組件中引入並注冊子組件,在父組件中傳入數據,為子組件的prop賦值,並在父組件中控制子組件的顯示。

使用父子組件 +局部注冊,無需關注子組件的創建,相對來說比較簡單。但是有時也會遇到問題:

  • 子組件的模板都是事先定義好的,如果我要從接口動態渲染組件模板怎么辦?
  • 子組件都是在父組件內定義好的位置渲染,假如想要在JS代碼中靈活調用,在任意地方渲染怎么辦?
    這時就輪到Vue.extend()出場了。

Vue.extend()

Vue.extend()Vue框架提供的全局api,查閱官網文檔,相關說明如下:vue.extend()接口說明

類比Java,可以將定義好的組件看成一個模板類,使用Vue.extend()生成該模板類的繼承子類。模板類中提供了默認的變量(模板、樣式、變量等),並定義了方法,在js代碼中可以繼承並覆蓋父類的變量和方法。Vue.extend()中接收的參數相當於子類的構造參數。

容易得出,我們需要傳入的是對話框綁定的數據模型(data),以及點擊確認后執行的方法。

  • Promise
    參考Element的做法,使用ES6中的Promise對象封裝構造函數的返回,能使代碼更加簡潔。

代碼實現

import Vue from 'vue';
import confirm from '../Comfirm.vue';
let confirmConstructor = Vue.extend(confirm);
let theConfirm = function (content) {
    return new Promise((res, rej) => {
        //promise封裝,ok執行resolve,no執行rejectlet
        let confirmDom = new confirmConstructor({
            el: document.createElement('div')
        })
        document.body.appendChild(confirmDom.$el); //new一個對象,然后插入body里面
        confirmDom.content = content; //為了使confirm的擴展性更強,這個采用對象的方式傳入,所有的字段都可以根據需求自定義
        confirmDom.ok = function () {
            res()
            confirmDom.isShow = false
        }
        confirmDom.close = function () {
            rej()
            confirmDom.isShow = false
        }

    })
}
export default theConfirm;

Confirm.vue

<template>
    <!-- 自定義確認彈窗樣式 -->
    <el-dialog width="600px" :title="content.title" :visible.sync="content.show" v-if="isShow">
        <span>{{ content.message }}</span>
        <div slot="footer" class="dialog-footer">
            <el-button @click="close">
                取 消
            </el-button>
            <el-button type="primary" @click="ok">
                確 定
            </el-button>
        </div>
    </el-dialog>

</template>

<script>
    export default {
        data() {
            return {
                // 彈窗內容
                isShow: true,
                content: {
                    title: "",
                    message: "",
                    data: "",
                    show: false
                }
            };
        },
        methods: {
            close() {
              
            },
            ok() {
   
            }
        }
    };
</script>

<style>
</style>

在main.js中引入

import confirm from '@/confirm.js' 
Vue.prototype.$confirm = confirm;

在任意方法中使用

 this.$confirm({ title: "刪除", message: "確認刪除該文件嗎?", show: true })
                    .then(() => {
                        //用戶點擊確認后執行

                    })
                    .catch(() => {
                    // 取消或關閉
                });
            }

總結

本篇主要涉及知識點:

  • Vue.prototypeVue實例添加方法
  • Vue.extend()的使用方法
  • Promise對象的定義和使用
    面向對象的思想,可復用、易擴展、易維護,是我們編程過程中應當時刻注意的原則。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM