最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從0到1解鎖Element-Plus組件二次封裝El-Dialog動態(tài)調用的原理解析

 更新時間:2025年07月07日 09:38:59   作者:hackchen  
作者通過二次封裝Element-Plus的el-dialog組件,實現(xiàn)動態(tài)顯示與數(shù)據(jù)傳遞功能,提升項目靈活性和代碼復用性,適用于用戶編輯、文件上傳確認、權限管理等多場景需求,本文給大家介紹從0到1解鎖Element-Plus組件二次封裝El-Dialog動態(tài)調用的原理解析,感興趣的朋友一起看看吧

技術難題初登場

家人們,最近在開發(fā)一個超復雜的后臺管理系統(tǒng)項目,里面有各種數(shù)據(jù)展示、表單提交、權限控制等功能,在這個過程中,我頻繁地使用到了element-plus組件庫中的el-dialog組件 。它就像一個小彈窗,可以用來顯示各種提示信息、編輯表單之類的。比如說在用戶點擊 “編輯” 按鈕時,就彈出一個el-dialog,里面放著編輯表單,讓用戶修改數(shù)據(jù)。

但隨著功能的不斷完善,我發(fā)現(xiàn)原生的el-dialog組件在某些場景下真的不夠靈活。比如說,我想在不同的組件中根據(jù)不同的業(yè)務邏輯動態(tài)地控制對話框的顯示和隱藏,還要傳遞不同的數(shù)據(jù)給對話框,原生組件用起來就很麻煩,每次都要寫很多重復的代碼,這可太影響開發(fā)效率了。所以,我就決定對el-dialog進行二次封裝,實現(xiàn)動態(tài)調用,讓它更好地滿足我的項目需求。接下來,就把我的經(jīng)驗分享給大家,一起看看怎么解決這個問題。

實現(xiàn)效果

代碼實現(xiàn)

import { ElButton, ElDialog } from "element-plus";
import { createApp, h } from "vue";
// 創(chuàng)建一個 DialogManager 類來管理對話框
class DialogManager {
  constructor() {
    this.dialogs = [];
  }
  /**
   * 創(chuàng)建并顯示一個動態(tài)對話框
   * @param {Object} options - 對話框配置選項
   * @returns {Object} - 返回對話框實例
   */
  create(options = {}) {
    // 合并默認配置
    const defaultOptions = {
      title: "提示",
      visible: true,
      fullscreen: false,
      top: "15vh",
      modal: true,
      lockScroll: true,
      closeOnClickModal: true,
      closeOnPressEscape: true,
      beforeClose: null,
      footerBtns: [
        {
          label: "取消",
          type: "default",
          handler: (instance) => {
            instance.close();
          },
        },
        {
          label: "確定",
          type: "primary",
          handler: (instance) => {
            instance.close();
          },
        },
      ],
    };
    const dialogOptions = { ...defaultOptions, ...options };
    // 創(chuàng)建一個容器元素
    const container = document.createElement("div");
    document.body.appendChild(container);
    // 創(chuàng)建 Dialog 組件實例
    const app = createApp({
      data() {
        return {
          dialogVisible: dialogOptions.visible,
        };
      },
      provide() {
        return {
          manager: this.$options.manager, // 提供manager
        };
      },
      inject: ["manager"], // 注入manager
      render() {
        const footerNodes = dialogOptions.footerBtns.map((btn, index) => {
          return h(
            ElButton,
            {
              key: index,
              type: btn.type || "default",
              size: "small",
              onClick: () => {
                if (btn.handler) {
                  btn.handler(this);
                }
              },
            },
            () => btn.label
          );
        });
        // 改進 content 渲染方式
        const renderContent = () => {
          if (typeof dialogOptions.content === "string") {
            return h("div", { class: "dialog-content" }, dialogOptions.content);
          } else if (dialogOptions.content) {
            // 只傳遞必要的屬性和方法
            const props = {
              // 提供關閉對話框的回調
              closeDialog: () => {
                this.close();
              },
              // 可以添加其他必要的屬性
            };
            // 如果有額外的 props,合并它們
            if (dialogOptions.contentProps) {
              Object.assign(props, dialogOptions.contentProps);
            }
            return h(dialogOptions.content, props);
          } else {
            return h("div", { class: "dialog-content" }, "No content provided");
          }
        };
        return h(
          ElDialog,
          {
            title: dialogOptions.title,
            modelValue: this.dialogVisible,
            "onUpdate:modelValue": (val) => {
              this.dialogVisible = val;
            },
            fullscreen: dialogOptions.fullscreen,
            top: dialogOptions.top,
            modal: dialogOptions.modal,
            lockScroll: dialogOptions.lockScroll,
            closeOnClickModal: dialogOptions.closeOnClickModal,
            closeOnPressEscape: dialogOptions.closeOnPressEscape,
            beforeClose: dialogOptions.beforeClose,
            onClose: () => {
              this.dialogVisible = false;
              if (dialogOptions.onClose) {
                dialogOptions.onClose(this);
              }
              // 延遲銷毀,讓關閉動畫完成
              setTimeout(() => {
                this.destroy();
              }, 300);
            },
          },
          {
            // 默認插槽用于對話框內(nèi)容
            default: renderContent,
            footer: () =>
              h(
                "div",
                {
                  class: "dialog-footer",
                },
                footerNodes
              ),
          }
        );
      },
      methods: {
        // 關閉對話框
        close() {
          this.dialogVisible = false;
        },
        // 銷毀對話框實例
        destroy() {
          app.unmount();
          if (container.parentNode) {
            container.parentNode.removeChild(container);
          }
          // 從管理列表中移除
          if (this.manager) {
            const index = this.manager.dialogs.indexOf(this);
            if (index !== -1) {
              this.manager.dialogs.splice(index, 1);
            }
          }
        },
      },
      mounted() {
        // 添加到管理列表
        if (this.manager) {
          this.manager.dialogs.push(this);
        } else {
          console.error("Manager is not initialized");
        }
      },
    }).provide("manager", this); // 全局提供manager
    // 掛載應用
    const instance = app.mount(container);
    instance.manager = this; // 直接在實例上設置manager
    return instance;
  }
  /**
   * 關閉所有對話框
   */
  closeAll() {
    this.dialogs.forEach((dialog) => {
      dialog.close();
    });
  }
}
// 創(chuàng)建單例實例
const dialogManager = new DialogManager();
// 導出創(chuàng)建對話框的函數(shù)
export function createDialog(options) {
  return dialogManager.create(options);
}
// 導出關閉所有對話框的函數(shù)
export function closeAllDialogs() {
  dialogManager.closeAll();
}

調用示例

-------------------------------- 基本文本對話框 -------------------------------------
import { createDialog } from '@/utils/dialog-manager';
export default {
  methods: {
    showSimpleDialog() {
      createDialog({
        title: '確認操作',
        content: '你確定要執(zhí)行這個操作嗎?',
        onClose: () => {
          console.log('對話框已關閉');
        },
        footerBtns: [
          {
            label: '取消',
            handler: (instance) => {
              console.log('點擊了取消');
              instance.close();
            },
          },
          {
            label: '確認',
            type: 'primary',
            handler: (instance) => {
              console.log('執(zhí)行確認操作');
              instance.close();
            },
          },
        ],
      });
    },
  },
};
-------------------------- 包含組件的對話框 --------------------------------
import { createDialog } from '@/utils/dialog-manager';
import MyComponent from '@/components/MyComponent.vue';
export default {
  methods: {
    showComponentDialog() {
      createDialog({
        title: '自定義組件對話框',
        content: MyComponent,
        contentProps: {     // 這里可以傳入組件的props
          message: '這是來自父組件的消息',
          src: 'xxx',
        },
        width: '600px',
        footerBtns: [
          {
            label: '關閉',
            handler: (instance) => {
              instance.close();
            },
          },
        ],
      });
    },
  },
};
-------------------------- 異步操作對話框 --------------------------------
import { createDialog } from '@/utils/dialog-manager';
export default {
  methods: {
    async showAsyncDialog() {
      const dialog = createDialog({
        title: '正在加載...',
        content: '數(shù)據(jù)加載中,請稍候...',
        showClose: false, // 隱藏關閉按鈕
        footerBtns: [],   // 不顯示底部按鈕
      });
      try {
        // 模擬異步操作
        const result = await this.fetchData();
        dialog.close();
        // 顯示成功消息
        createDialog({
          title: '操作成功',
          content: '數(shù)據(jù)加載完成',
          footerBtns: [
            {
              label: '確定',
              type: 'primary',
              handler: (instance) => instance.close(),
            },
          ],
        });
      } catch (error) {
        dialog.close();
        // 顯示錯誤消息
        createDialog({
          title: '操作失敗',
          content: `錯誤: ${error.message}`,
          footerBtns: [
            {
              label: '關閉',
              handler: (instance) => instance.close(),
            },
          ],
        });
      }
    },
  },
};

原理剖析

這里面的原理其實也不難理解,主要是利用了Vue的響應式原理 。我們都知道,在Vue中,數(shù)據(jù)發(fā)生變化時,視圖會自動更新。我們封裝的組件就是基于這個特性,通過一個響應式的變量來控制el-dialog的顯示與隱藏。比如說,我們定義一個isDialogVisible變量,當它為true時,el-dialog就顯示,為false時就隱藏 。

而動態(tài)傳遞參數(shù)呢,則是通過props來實現(xiàn)的。我們在封裝的組件中定義好props,然后在調用組件的時候,就可以把需要的數(shù)據(jù)通過props傳遞進去,這樣對話框就能根據(jù)不同的數(shù)據(jù)展示不同的內(nèi)容啦 。比如說,我們要在對話框里顯示不同的提示信息,就可以把提示信息作為props傳遞給對話框組件 。再結合provideinject,它們就像是一座橋梁,能夠讓不同層級的組件之間方便地進行通信,讓數(shù)據(jù)的傳遞更加靈活 。

實際應用場景

經(jīng)過二次封裝實現(xiàn)動態(tài)調用的el-dialog在實際項目中的應用場景可太廣泛了 。比如說在用戶信息編輯場景,當用戶點擊 “編輯” 按鈕,就可以動態(tài)彈出我們封裝好的對話框,里面填充好用戶當前的信息,用戶修改完成后點擊確認,就能提交新的信息,整個過程非常流暢自然 。

在文件上傳確認場景,當用戶選擇好文件準備上傳時,彈出對話框讓用戶確認文件信息,比如文件名、文件大小等 。如果沒問題再點擊上傳,這樣可以避免用戶誤操作上傳錯誤的文件 。還有在權限管理中,當管理員要給某個用戶分配新的權限時,通過動態(tài)調用對話框,展示所有權限選項,管理員勾選后提交,就能完成權限分配,操作簡單又高效 。

總結

經(jīng)過二次封裝實現(xiàn)動態(tài)調用的el-dialog組件,不僅大大提高了代碼的復用性,讓我們在不同的業(yè)務場景中能夠輕松應對對話框的各種需求,還增強了項目的靈活性和可維護性。以前寫一堆重復代碼的日子一去不復返啦!

強烈建議各位小伙伴在自己的項目中也嘗試應用這種二次封裝的方法 ,相信你們會發(fā)現(xiàn)它的強大之處。要是在實踐過程中有什么經(jīng)驗,或者遇到了問題,都歡迎在評論區(qū)留言分享。咱們一起交流,共同進步 !

到此這篇關于從0到1解鎖Element-Plus組件二次封裝El-Dialog動態(tài)調用的文章就介紹到這了,更多相關Element-Plus二次封裝El-Dialog內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Vue通過moment插件實現(xiàn)獲取當前月的第一天和最后一天

    Vue通過moment插件實現(xiàn)獲取當前月的第一天和最后一天

    這篇文章主要介紹了Vue 結合插件moment 實現(xiàn)獲取當前月的第一天和最后一天,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-10-10
  • vite+vue3+ts項目中提示無法找到模塊的問題及解決

    vite+vue3+ts項目中提示無法找到模塊的問題及解決

    這篇文章主要介紹了vite+vue3+ts項目中提示無法找到模塊的問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Vue創(chuàng)建頭部組件示例代碼詳解

    Vue創(chuàng)建頭部組件示例代碼詳解

    本文通過實例代碼給大家介紹了Vue創(chuàng)建頭部組件的相關知識,非常不錯,具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2018-10-10
  • Vue實現(xiàn)圖片與文字混輸效果

    Vue實現(xiàn)圖片與文字混輸效果

    用多了 JQuery ,習慣了使用JQuery的API操作 DOM ,幾乎忘記了原生JS對DOM操作,今天在項目中遇到了文字和圖片混輸?shù)那闆r,小編給大家分享Vue實現(xiàn)圖片與文字混輸效果,感興趣的朋友一起看看吧
    2019-12-12
  • vue如何自定義配置運行run命令

    vue如何自定義配置運行run命令

    這篇文章主要介紹了vue如何自定義配置運行run命令,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue實現(xiàn)滾動加載更多效果的示例代碼

    Vue實現(xiàn)滾動加載更多效果的示例代碼

    這篇文章介紹了在?Web?應用中處理大量數(shù)據(jù)展示的兩種滾動加載更多方案,滾動加載更多通過分頁工作,優(yōu)點是實現(xiàn)簡單、用戶體驗流暢,缺點是內(nèi)存占用可能過高,虛擬列表只渲染視口內(nèi)容,性能好但實現(xiàn)復雜,本文介紹了Vue實現(xiàn)滾動加載更多效果,需要的朋友可以參考下
    2024-12-12
  • 前端儲存之localStrage、sessionStrage和Vuex使用

    前端儲存之localStrage、sessionStrage和Vuex使用

    localStorage、sessionStorage和Vuex是三種不同的客戶端存儲方式,用于在瀏覽器中保存數(shù)據(jù),localStorage和sessionStorage都是以鍵值對的形式存儲數(shù)據(jù),但localStorage存儲的數(shù)據(jù)在關閉瀏覽器后仍然存在
    2025-01-01
  • Vue實現(xiàn)移動端日歷的示例代碼

    Vue實現(xiàn)移動端日歷的示例代碼

    工作中遇到一個需求是根據(jù)日歷查看某一天/某一周/某一月的睡眠報告,但是找了好多日歷組件都不是很符合需求,只好自己手寫一個日歷組件,順便記錄一下,希望對大家有所幫助
    2023-04-04
  • vue + echarts實現(xiàn)中國省份地圖點擊聯(lián)動

    vue + echarts實現(xiàn)中國省份地圖點擊聯(lián)動

    這篇文章主要介紹了vue + echarts實現(xiàn)中國地圖省份點擊聯(lián)動,需要的朋友可以參考下
    2022-04-04
  • vue權限路由實現(xiàn)的方法示例總結

    vue權限路由實現(xiàn)的方法示例總結

    這篇文章主要給大家介紹了關于vue權限路由實現(xiàn)方法的相關資料,文中通過示例代碼介紹地方非常詳細,對大家學習或者使用vue具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-07-07

最新評論

筠连县| 江川县| 阳原县| 中阳县| 秭归县| 若羌县| 汝阳县| 泰宁县| 江川县| 咸丰县| 尉氏县| 芜湖县| 东莞市| 改则县| 喀什市| 台东市| 河西区| 永靖县| 庄浪县| 三原县| 香格里拉县| 边坝县| 临颍县| 抚州市| 承德县| 富平县| 禹州市| 鸡泽县| 花莲市| 嘉祥县| 溆浦县| 成武县| 鸡东县| 丽江市| 科技| 长阳| 榆社县| 古蔺县| 伊通| 闵行区| 龙州县|