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

vue.js前端網(wǎng)頁彈框異步行為示例分析

 更新時間:2021年11月25日 09:37:32   作者:廈門在乎科技  
這篇文章主要為大家介紹了vue.js前端網(wǎng)頁彈框異步的行為示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助祝大家多多進步,早日升職加薪

1. 序

網(wǎng)頁彈框是個很常見的功能,比如需要告知用戶消息的時候 (Alert),需要用戶進行確認的時候 (Confirm),需要用戶補充一點信息的時候 (Prompt) …… 甚至可以彈框讓用戶填寫表單 (Modal Dialog)。

彈框之后,開發(fā)者需要知道這個彈框是什么時候關閉以便進行接下來的操作。

在比較古老的 UI 組件中,這個事情是通過事件回調(diào)來進行的,大概長這樣:

showDialog(content, title, {
    closed: function() { console.log("對話框已關閉"); }
})

不過對話框的行為。你看,它彈出來了,但它不會阻塞后面的代碼,而且開發(fā)者并不知道什么時候關閉,因為這是用戶行為。既然是異步,封裝成 Promise 使用?await?語法來調(diào)用會更舒服一些。簡單的封裝大概可以這樣:

async function asyncShowDialog(content, title, options) {
    return new Promise(resolve => {
        showDialog(content, title, {
            ...options,
            closed: resolve
        });
    });
}
 
(async () => {
    await asyncShowDialog(content, title);
    console.log("對話框已關閉");
})();

彈框的基本的異步行為就是這么簡單,就這么結束?心有不甘,再研究研究!

2. 找兩個彈框組件看看

Ant Design Vue 使用了事件的形式,點擊“確定”按鈕會觸發(fā)?ok?事件,點擊“取消”或者右上角的關閉按鈕會觸發(fā)?cancel?事件。

這兩個事件處理函數(shù)通過參數(shù)對象的?onOk?和?onCancel?屬性掛載進去??雌饋砥降瓱o奇,但如果處理事件返回的是一個 Promise 對象,點擊按鈕之后會出現(xiàn)加載動畫并等待直到 Promise 對象完成之后才會關閉對話框。這種設計把異步等待動畫組合到彈框當中,簡潔直觀,代碼寫起來也很方便。以 confirm 對話框為例:

Modal.confirm({
    ...
    onOk() {
        // 點擊「確定」按鈕后,會顯示加載動畫,并在一秒后關閉對話框
        return new Promise(resolve => {
            setTimeout(resolve, 1000);
        });
    }
    ...
});

而 Element Plus 使用了 Promise 形式,打開對話框時,并不是把確定或取消的處理函數(shù)以參數(shù)的形式傳入,而是直接返回一個 Promise 對象,供開發(fā)者通過?.then()/.catch()?或者?await?處理。示例:

try {
    await ElMessageBox.confirm(...);
    // 按下確定按鈕在這里處理
} catch(err) {
    // 按下取消按鈕在這里處理
}

Element Plus 的這種處理方式,要在對話框關閉之后才能處理業(yè)務。這也是使用 Promise 的局限 —— 對于一個已經(jīng)封裝好的 Promise 對象,很難在其中插入新的邏輯。

如果使用?ElMessageBox?的時候也想像 Ant Design 那樣在關閉前進行一些異步操作,只能去找找看它是否提供了關閉前的處理事件。一找還真找到了,它有?beforeClose?事件。該事件的處理函數(shù)簽名是?beforeClose(action, instance, done)

action?表示按了哪個按鈕,取值可能是?"confirm"、"cancel"?和?"close"(不用解釋了吧)。

instance?是 MessageBox 實例,可以使用它來控制一些界面效果,比如

instance.confirmButtonLoading = true?會在“確定”按鈕上顯示加載動畫,instance.confirmButtonText?可以用來改變按鈕文本 …… 這些操作在進行異步等待時可以提供更好的用戶體驗。

done?是一個函數(shù),調(diào)用它表示?beforeClose()?的異步處理完成,對話框現(xiàn)在可以關閉了!

所以類似 Ant Design 的處理可以這樣寫:

try {
    await ElMessageBox.confirm({
        ...
        beforeClose: async (action, instance, done) => {
            await new Promise(resolve => setTimeout(resolve, 1000));
            done();
        }
    });
    // 按下確定按鈕在這里處理
} catch(err) {
    // 按下取消按鈕在這里處理
}

3. 自己肝一個

分析了兩個彈框組件的行為處理,我們已經(jīng)知道,一個體驗良好的彈框組件應該具備如下特征:

  • 提供基于 Promise 的異步控制能力(Ant Design Vue 雖然沒有提供,但是像“序”中那樣封裝一下就可以)。
  • 允許在關閉前進行一些操作,甚至是異步操作。
  • 提供異步加載過程中的界面反饋,而且最好不需要開發(fā)者來控制(從這點來說 Ant Design 比 Element Plus 方便)。

接下來,我們自己寫一個,看看是如何實現(xiàn)上述特征的。不過,既然我們主要研究的是行為而不是數(shù)據(jù)處理,所以不用 Vue 框架,直接用 DOM 操作,然后引入 jQuery 來簡化 DOM 處理。

對話框的 HTML 骨架也比較簡單:下面一層蒙板,上面一個固定大小的?<div>?層,內(nèi)部再用?<div>?劃分成標題、內(nèi)容、操作區(qū)三塊:

<div class="dialog" id="dialogTemplate">
  <div class="dialog-window">
    <div class="dialog-title">對話框標題</div>
    <div class="dialog-content">對話框的內(nèi)容</div>
    <div class="dialog-operation">
      <button type="button" class="ensure-button">確定</button>
      <button type="button" class="cancel-button">取消</button>
    </div>
  </div>
</div>

這里把它定義成一個模板,希望每次都從它克隆一個 DOM 出來呈現(xiàn),關閉即毀。

樣式表的內(nèi)容較長,可以從后面的示例鏈接去獲取。代碼及代碼的進化過程才是本文的重點。

最簡單的呈現(xiàn)是利用 jQuery 克隆一個顯示出來,但顯示前一定要記得刪除掉?id?屬性,并把它添加到?<body>?中去:

$("#dialogTemplate").clone().removeAttr("id").appendTo("body").show();

把它封裝成一個函數(shù),并且添加對「確定」和「取消」按鈕的處理:

function showDialog(content, title) {
    const $dialog = $("#dialogTemplate").clone().removeAttr("id"); 
    // 設置對話框的標題和內(nèi)容(簡單示例,所以只處理文本)
    $dialog.find(".dialog-title").text(title);
    $dialog.find(".dialog-content").text(content); 
    // 通過事件代理(也可以不用代理)處理兩個按鈕事件
    $dialog
        .on("click", ".ensure-button", () => {
            $dialog.remove();
        })
        .on("click", ".cancel-button", () => {
            $dialog.remove();
        }); 
    $dialog.appendTo("body").show();
}

彈框的基本邏輯就出來了?,F(xiàn)在做兩點優(yōu)化:① 把?$dialog.remove()?封裝成函數(shù),便于對關閉對話框進行統(tǒng)一處理(代碼復用) ② 使用?.show()?呈現(xiàn)太過生硬,改為?fadeIn(200);同理,應該在?.remove()?之前先fadeOut(200)。

function showDialog(...) {
    ... 
    const destory = () => {
        $dialog.fadeOut(200, () => $dialog.remove());
    }; 
    $dialog
        .on("click", ".ensure-button", destroy)
        .on("click", ".cancel-button", destroy); 
    $dialog.appendTo("body").fadeIn(200);
}

3.1. 封裝 Promise

到這一步,彈框已經(jīng)可以正常彈出/關閉了,但是沒辦法注入「確定」或「取消」的邏輯代碼。前面提到可以通過事件或 Promise 兩種形式來提供接口,這里使用 Promise 的方式。如果點「確定」就 resolve,點「取消」就 reject。

function showDialog(...) {
    ... 
    const promise = new Promise((resolve, reject) => {
        $dialog
            .on("click", ".ensure-button", () => {
                destroy();
                resolve("ok");
            })
            .on("click", ".cancel-button", () => {
                destroy();
                reject("cancel");
            });
    }); 
    $dialog.appendTo("body").fadeIn(200);
    return promise();
}

封裝好了,但有個問題:destroy()?是個異步過程,但代碼并沒有等它結束,所以?showDialog()?完成異步處理之后還在進行?fadeOut()?操作和?remove()?操作。要解決這個問題,只能封裝?destory()。當然調(diào)用的時候也別忘了加?await,而加?await?就要把外層函數(shù)聲明為?async

function showDialog(...) {
    ...
    const destory = () => {
        return new Promise(resolve => {
            $dialog.fadeOut(200, () => {
                $dialog.remove();
                resolve();
            });
        });
    };
     const promise = new Promise((resolve, reject) => {
        $dialog
            .on("click", ".ensure-button", async () => {
                await destroy();
                resolve("ok");
            })
            .on("click", ".cancel-button", async () => {
                await destroy();
                reject("cancel");
            });
    }); 
    ...
}

3.2. 確定時允許異步等待

不管「確定」還是「取消」都可以保持彈框顯示,進行異步等待。但作為示例,這里只處理「確定」的情況。

這個異步等待過程要注入到從彈窗中,只能采用參數(shù)注入的形式。所以需要為?showDialog()?添加一個?options?參數(shù),允許注入一個處理函數(shù)給?onOk?屬性,如果這個處理函數(shù)返回 Promise Like,就進行異步等待。

先修改?showDialog()?接口:

function showDialog(conent, title, options = {}) { ... }

然后再處理?$dialog.on("click", ".ensure-button", ...)?事件:

$dialog
    .on("click", ".ensure-button", async () => {
        const { onOk } = options;
        // 從 options 中拿到 onOk,如果它是一個函數(shù)才需要等待處理
        if (typeof onOk === "function") {
            const r = onOk();
            // 判斷 onOk() 的結果是不是一個 Promise Like 對象
            // 只有 Promise Like 對象才需要異步等待
            if (typeof r?.then === "function") {
                const $button = $dialog.find(".ensure-button");
                // 異步等待過程中需要給用戶一定反饋
                // 這里偷懶沒有使用加載動畫,只用文字來進行反饋
                $button.text("處理中...");
                await r;
                // 因為在完成之后,關閉之前有 200 毫秒的漸隱過程,
                // 所以把按鈕文本改為“完成”,給用戶及時反饋是有必要的
                $button.text("完成");
            }
        }
        await destroy();
        resolve("ok");
    })

現(xiàn)在這個彈框的行為基本上處理完了,調(diào)用的示例:

const result = await showDialog(
    "你好,這里是對話框的內(nèi)容",
    "打個招呼",
    {
        onOk: () => new Promise((resolve) => { setTimeout(resolve, 3000); })
    }
).catch(msg => msg);  // 這里把取消引起的 reject 變成 resolve,避免使用 try...catch...
 
console.log(result === "ok" ? "按下確定" : "按下取消");

3.3. 細節(jié)完善

都有對話框了最后還用?console.log(...)?實在有點不妥,直接彈框提示消息不更好?

但是現(xiàn)在的?showDialog()?只處理了 Confirm 彈框,沒有處理 Alert 彈框 …… 問題不大,在?options?里加個?type?好了。如果?type?是?"alert"?就把「取消」按鈕干掉。

async function showDialog(content, title, options = {}) {
    ...
    
    if (options.type === "alert") {
        $dialog.find(".cancel-button").remove();
    }    
    ...
}

然后,最后的?console.log(...)?可以進化一下:

showDialog(result === "ok" ? "按下確定" : "按下取消", "提示", { type: "alert" });

3.4. 改革

如果不喜歡在?options?中注入處理函數(shù),還可以換個法子,在返回的 Promise 對象中注入。先在?.ensure-button?的事件中把?const { onOk } = options?改為?const { onOk } = promise,也就是從?promise?中獲取注入的?onOk。然后改調(diào)用部分:

const dialog = showDialog("你好,這里是對話框的內(nèi)容", "打個招呼");
// 把處理函數(shù)注入到 promise 的 onOk
dialog.onOk = () => new Promise((resolve) => { setTimeout(resolve, 3000); });
const result = await dialog.catch(msg => msg);
showDialog(result === "ok" ? "按下確定" : "按下取消", "提示", { type: "alert" });

這里有幾點要注意:

dialog?必須只能是?showDialog()?直接返回的。如果調(diào)用了?.catch()?將會得到另一個 Promise 對象,此時再注入?onOk?就注入不到?showDialog()?里面產(chǎn)生的那個 Promise 對象上了。

showDialog()?不能聲明為?async?的,否則返回出來的 Promise 對象也不是里面產(chǎn)生的那一個。

別忘了?await。

以上就是vue.js前端網(wǎng)頁彈框異步行為示例分析的詳細內(nèi)容,更多關于vue.js前端異步網(wǎng)頁彈框的資料請關注腳本之家其它相關文章!

相關文章

  • 前端vue3中的ref與reactive用法及區(qū)別總結

    前端vue3中的ref與reactive用法及區(qū)別總結

    這篇文章主要給大家介紹了關于前端vue3中的ref與reactive用法及區(qū)別的相關資料,關于ref及reactive的用法,還是要在開發(fā)中多多使用,遇到響應式失效問題,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-08-08
  • 如何使用vue slot創(chuàng)建一個模態(tài)框的實例代碼

    如何使用vue slot創(chuàng)建一個模態(tài)框的實例代碼

    這篇文章主要介紹了如何使用vue slot創(chuàng)建一個模態(tài)框,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • Vue中的 mixins 和 provide/inject詳解

    Vue中的 mixins 和 provide/inject詳解

    這篇文章主要介紹了Vue中的 mixins 和 provide/inject詳解,本文結合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • vue前端靈活改變后端地址兩種方式

    vue前端靈活改變后端地址兩種方式

    最近在學習或工作中遇到,把Vue前端項目打包后,要求可以再次修改請求后端接口的基礎地址,下面這篇文章主要給大家介紹了關于vue前端靈活改變后端地址的兩種方式,需要的朋友可以參考下
    2024-03-03
  • vue3利用keepAlive緩存頁面實例詳解

    vue3利用keepAlive緩存頁面實例詳解

    <keep-alive> 是一個抽象組件,它自身不會渲染一個DOM元素,也不會出現(xiàn)在組件的父組件鏈中,下面這篇文章主要給大家介紹了關于vue3利用keepAlive緩存頁面的相關資料,需要的朋友可以參考下
    2022-11-11
  • vue3 微信掃碼登錄及獲取個人信息實現(xiàn)的三種方法

    vue3 微信掃碼登錄及獲取個人信息實現(xiàn)的三種方法

    本文主要介紹了vue3 微信掃碼登錄及獲取個人信息實現(xiàn)的三種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • vue中使用h5 video標簽實現(xiàn)彈窗播放本地視頻的方法

    vue中使用h5 video標簽實現(xiàn)彈窗播放本地視頻的方法

    本文主要介紹了vue中使用h5 video標簽實現(xiàn)彈窗播放本地視頻的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-04-04
  • vue2.0構建單頁應用最佳實戰(zhàn)

    vue2.0構建單頁應用最佳實戰(zhàn)

    這篇文章主要為大家分享了vue2.0構建單頁應用最佳實戰(zhàn)案例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 原生echart和vue-echart的使用詳解

    原生echart和vue-echart的使用詳解

    這篇文章主要為大家詳細介紹了原生echart和vue-echart的使用,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • Vue.js實現(xiàn)數(shù)據(jù)雙向綁定的代碼示例

    Vue.js實現(xiàn)數(shù)據(jù)雙向綁定的代碼示例

    在我們使用vue的時候,當數(shù)據(jù)發(fā)生了改變,界面也會跟著更新,但這并不是理所當然的,我們修改數(shù)據(jù)的時候vue是如何監(jiān)聽數(shù)據(jù)的改變以及當數(shù)據(jù)發(fā)生改變的時候vue如何讓界面刷新的,所以本文就給大家講講Vue.js 數(shù)據(jù)雙向綁定是如何實現(xiàn)的
    2023-07-07

最新評論

光泽县| 花莲县| 博野县| 贵南县| 老河口市| 怀柔区| 咸宁市| 香格里拉县| 康马县| 上杭县| 普安县| 徐水县| 新津县| 安吉县| 安福县| 新建县| 洪江市| 公安县| 诏安县| 古田县| 肥西县| 北宁市| 常山县| 新安县| 田阳县| 南陵县| 鄂托克前旗| 平和县| 隆林| 东乡| 松桃| 济宁市| 太原市| 噶尔县| 宁乡县| 吴桥县| 宁化县| 南郑县| 德阳市| 铁岭市| 洪泽县|