欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Ant-design-vue的Modal彈窗 封裝 命令式與Hooks用法

 更新時(shí)間:2023年06月15日 11:10:39   作者:JiangHong  
這篇文章主要給大家介紹了基于Ant-design-vue的Modal彈窗封裝命令式與Hooks用法,文中有詳細(xì)的代碼示例,具有一定的參考價(jià)值,感興趣的同學(xué)可以借鑒閱讀

前言

通常大家在使用彈窗有多樣化的使用方式,常見的是直接使用該 Modal 組件,然后顯隱的狀態(tài)放在父容器里面維護(hù)。

其次就是在全局掛載一個(gè)公共的彈窗組件,然后通過 store 來傳遞不同的參數(shù),并且通過 store 中的方法來改變 state.visble 的狀態(tài),從而使得彈窗展示。

雖然說這些種方式可以實(shí)現(xiàn)同等功能,但總覺得用的不是很直接, 邏輯片段寫的也很分散, 后期代碼量越多維護(hù)成本越高,那有沒有一種比較好的思路處理這個(gè)問題呢?將邏片段進(jìn)行統(tǒng)一管理。

下面我逐一說一下正常開發(fā)中 model 彈窗的組件和我自己研究出來的使用方式,在 命令式hooks 兩種方式中可以完全的解決代碼邏輯分散問題。

組件式-用法

使用方式

<template>
  <Modal v-model:visible="visible" title="彈窗"> ...content </Modal>
  <Button type="primary" @click="visible = true">打開彈窗</Button>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import { Modal, Button } from "ant-design-vue";
export default defineComponent({
  components: {
    Modal,
    Button,
  },
  setup() {
    const visible = ref(false);
    return { visible };
  },
});
</script>

組件式用法也可以說是傳統(tǒng)用法實(shí)際就是把市面上一些封裝好的ui組件導(dǎo)入進(jìn)來使用,或者是自己封裝的組件。這樣使用確實(shí)很方便也很快捷。

比如說現(xiàn)在有一個(gè)需求,在當(dāng)前頁面中有 2 按鈕需要打開 2 個(gè)不同的彈窗。此時(shí)我們需要在當(dāng)前組件中聲明 2 個(gè) visible 初始值為 ref(false) 的變量,這還僅僅是控制一個(gè)顯隱的功能,那么隨著業(yè)務(wù)的復(fù)雜度增加,當(dāng)前頁面需要打開彈窗的按鈕增加,那么當(dāng)前組件就會(huì)變得越來越復(fù)雜,維護(hù)成本隨之也會(huì)增高。很有可能一個(gè)邏輯清晰的組件就會(huì)變得如下代碼一樣。

<template>
  <Modal v-model:visible="editVisible" title="彈窗">
    <Form>
      <FormItem label="名稱">
        <Input v-memo="editFormData.name" placeholder="請(qǐng)輸入" />
      </FormItem>
    </Form>
  </Modal>
  <Button type="primary" @click="editVisible = true">修改數(shù)據(jù)</Button>
  <Modal v-model:visible="detailVisible" title="彈窗"> ...detailContent </Modal>
  <Button type="primary" @click="detailVisible = true">查看詳情</Button>
</template>
<script lang="ts">
import { defineComponent, reactive, ref } from "vue";
import { Modal, Button, Form, FormItem, Input } from "ant-design-vue";
export default defineComponent({
  components: {
    Modal,
    Button,
    Form,
    FormItem,
    Input,
  },
  setup() {
    const editVisible = ref(false);
    const detailVisible = ref(false);
    const editFormData = reactive({ name: "" });
    return { editVisible, detailVisible, editFormData };
  },
});
</script>

隨隨便便增加一點(diǎn)業(yè)務(wù)邏輯兩個(gè)彈窗組件的數(shù)據(jù)就會(huì)混在一起,當(dāng)然我們可以把彈窗渲染的一部分內(nèi)容抽離出來,這樣也不能排除你增加按鈕的邏輯。

命令式-用法

使用方式

<template>
  <Button @click="openAModal"></Button>
</template>
<script>
import { Button } from "ant-design-vue";
import openAModal from "./openAModal";
export default defineComponent({
  components: {
    Button,
  },
  setup() {
    return {
      openAModal,
    };
  },
});
</script>

通過以上代碼,可以看出命令式使用方式要比組件式 使用方式簡(jiǎn)單的多,直接調(diào)用一個(gè)方法就可以實(shí)現(xiàn)同等等功能,非常的快捷方便,后期需要修改業(yè)務(wù)路基即可一針見血的直接奔向這個(gè)方法來做修改就好,相比組件式用法也更易于維護(hù)。

使用命令式用法,我們需要?jiǎng)?chuàng)建一個(gè)工具函數(shù)來包裝一下 Modal。下面的代碼是針對(duì) ant-design-vue@2.x 做的封裝這部分的邏輯我就不分析了,主要是看如何使用這個(gè)命令式的調(diào)用方法,感興趣的同仁們,可以自行研究。當(dāng)然下面代碼也針對(duì)于 antModal 特殊優(yōu)化了一下,用過的人可能知道 使用Ant Modal如果對(duì) onOk 事件不做處理的話他是無法主動(dòng)關(guān)閉彈窗的。而且 ant ModalokText、cancelText 一定要給一個(gè)名稱 不然他默認(rèn)第一次顯示的是中文,關(guān)閉后再次打開卻是英文。

核心實(shí)現(xiàn)邏輯

// modal.js
import { createVNode, render as vueRender } from "vue";
import { Modal as AntModal } from "ant-design-vue";
/**
 * @param {import("vue").DefineComponent} content
 * @param {import("vue").Prop} props
 * @param {Omit<import("ant-design-vue").ModalProps, 'visible'>} config
 */
export default function modal(content, props, config) {
  const container = document.createDocumentFragment();
  const _contentVnode = createVNode(content, props);
  const metadata = Object.create({
    okText: "確定",
    cancelText: "取消",
    visible: true,
    ...config,
  });
  metadata.onCancel = async function (...arg) {
    await config.onCancel?.(...arg);
    close();
  };
  metadata.onOk = async function () {
    if (!(config.onOk instanceof Function)) {
      close();
      return;
    }
    const result = config.onOk();
    if (!(result instanceof Promise)) {
      close();
      return;
    }
    update({ confirmLoading: true });
    return result
      .then(() => {
        update({ confirmLoading: false });
        close();
      })
      .catch(() => {
        update({ confirmLoading: false });
      });
  };
  let vm = createVNode(AntModal, metadata, () => _contentVnode);
  /**
   *
   * @param {typeof config} config
   */
  function update(config) {
    Object.assign(vm.component.props, config);
    vm.component.update();
  }
  function close() {
    metadata.visible = false;
    update(metadata);
  }
  function destroy() {
    if (vm) {
      vueRender(null, container);
      vm = null;
    }
  }
  /** 渲染 */
  vueRender(vm, container);
  return {
    ..._contentVnode,
    close,
    destroy,
    update,
  };
}

主要工具實(shí)現(xiàn)完了后,現(xiàn)在假設(shè)有一個(gè) A.vue 的組件,需要在 modal 彈窗中渲染,并且支持一個(gè)可配的 title ,通常我們的寫法是直接在 template中寫入 <Modal> <A title="名稱" /> </Modal>,但這次我們不這么做,我們先寫一個(gè) A.vue的組件 代碼如下:

// A.vue
<template>
  <h1>我是A組件</h1>
  <div>{{ title }}</div>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
  props: {
    title: {
      type: String,
      default: "",
    },
  },
});
</script>

現(xiàn)在基于 A.vue 來聲明一個(gè)調(diào)用彈窗的方法,因?yàn)闆]有業(yè)務(wù)場(chǎng)景 所以下面的方法簡(jiǎn)單點(diǎn)沒有去設(shè)置形參,如果后面業(yè)務(wù)有需求可以傳遞參數(shù)來使用。代碼如下:

// openAModal.js
import A from './A.vue'
import modal from './modal.js'
export default function openAModal() {
    modal(A, {title: 'A組件的props'}, {...彈窗的配置項(xiàng)})
}

后面使用直接調(diào)用 openAModal 即可在彈窗中展現(xiàn) A.vue。這樣在使用的時(shí)候無需在意 template 結(jié)構(gòu),更不用去聲明 visible 的屬性,彈窗的邏輯也不會(huì)與業(yè)務(wù)混合在一起,后期也方便維護(hù),完全符合設(shè)計(jì)原則中的單一職責(zé)。

當(dāng)然這樣也會(huì)有缺陷,因?yàn)閺棿敖M件是使用 render 函數(shù)渲染的,所以在modal 中的組件無法獲取到 vue 實(shí)例中全局注冊(cè)的一些方法,比如你全局 app.use(router),那么你在 A.vue 中是無法通過 useRouter() 來獲取路由實(shí)例。

通常這樣打開彈窗,組件內(nèi)使用的參數(shù)建議以傳遞參數(shù)的形式,不要全局獲取。 如果你非要在組件中使用 useRouteruseStore 等一些全局注冊(cè)的工具,請(qǐng)繼續(xù)閱讀下面的 hooks 用法,該方法模擬了 arco-design-reactuseModal 用法,相對(duì)命令式封裝做的事情要少的多。

Hooks-用法

使用方式

<template>
  <component :is="contextHolder" />
  <Button @click="openAModal">打開彈窗</Button>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { Button } from "ant-design-vue";
import useModal from "./useModal.js";
import A from "./A.vue";
export default defineComponent({
  components: {
    Button,
  },
  setup() {
    const [modal, contextHolder] = useModal({ title: "彈窗", content: A });
    return {
      openAModal: modal.show,
      contextHolder,
    };
  },
});
</script>

通過以上使用示例,使用方式類似于命令式,也是調(diào)用api去操作彈窗。但是比 命令式 多了一個(gè) contextHolder,為了處理 modal 不脫離當(dāng)前 vue 的實(shí)例,直接借助于vue component 組件去渲染當(dāng)前我們自己定義的 Component。這樣一來完美的解決了 命令式 調(diào)用方法的缺陷問題。

hook 的使用方式,應(yīng)該也可說是一種高級(jí)封裝組件的方式,需要傳遞一個(gè)你要渲染的組件然后,暴露一個(gè) contextHolder 和一些 Api 即可, 然后操作當(dāng)前hooks的 Api 來控制 modal

核心實(shí)現(xiàn)邏輯

// useModal
import { createVNode, ref, defineComponent } from "vue";
import { Modal as AntModal } from "ant-design-vue";
/**
 * @typedef {ReturnType<typeof defineComponent>} Component
 * @typedef {Omit<import("ant-design-vue").ModalProps, 'visible'>} ModalProps
 * @param {Omit<import("ant-design-vue").ModalProps, 'visible'> & {content: Component}} props
 *
 * @returns {[{show:() => void}, Component]}
 */
export default function useModal(props = {}) {
  const visible = ref(false);
  // 定義需要渲染的組件即Modal
  const contextHolder = defineComponent({
    render() {
      return createVNode(AntModal, { ...props, visible: visible.value }, () =>
        createVNode(props.content)
      );
    },
  });
  const show = () => {
    visible.value = true;
  };
  return [{ show }, contextHolder];
}
}

上面簡(jiǎn)單的實(shí)現(xiàn)了一個(gè) useModal ,使用 jsDoc 定義了一下入?yún)⒑头祷貐?shù),可以看到出來入?yún)⒃诨?modalprops基礎(chǔ)之上增加了一個(gè)content 屬性,就是用來接受你要渲染不同的組件的。

useModal 簡(jiǎn)單的暴露了一個(gè) show 方法,還有一些方法大家都可以自由發(fā)揮的,比如說,傳入的組件怎么怎么傳參數(shù),傳入的組件props變更怎么去更新,點(diǎn)擊 onOk 的時(shí)候怎么獲取到傳入組件的里面的數(shù)據(jù)。這些都是可以通過方法去實(shí)現(xiàn)的,一些邊界問題我就沒有去細(xì)處理了。主要能夠了解這種寫法的思路。有思路之后,就可以隨意改造。并且還能保留原有的類型提示。讓你在使用與排錯(cuò)的時(shí)候不會(huì)迷路。

總結(jié)

相對(duì)于正常開發(fā)我們使用了 vuerender 、component 的 is 、createVnode,借助了 arco-design-react 封裝的 useModalant-design-vueModal.confirm 思路來自動(dòng)動(dòng)手改造了一版,vue 版本的 useModal命令式 的使用方法。當(dāng)然如果能夠在vue中熟練使用 jsx 語法, 那基于這個(gè)封裝簡(jiǎn)直是再簡(jiǎn)單不過了。

最后感謝大家的閱讀,希望本文對(duì)你在前端開發(fā)的學(xué)習(xí)和實(shí)踐中有所幫助。繼續(xù)保持好奇心,追求卓越,享受前端開發(fā)的旅程!

以上就是基于Ant-design-vue的Modal彈窗封裝命令式與Hooks用法的詳細(xì)內(nèi)容,更多關(guān)于Ant-design-vue彈窗封裝與Hooks用法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 深入學(xué)習(xí)Vue nextTick的用法及原理

    深入學(xué)習(xí)Vue nextTick的用法及原理

    這篇文章主要介紹了深入學(xué)習(xí)Vue nextTick的用法及原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • 最后說說Vue2 SSR 的 Cookies 問題

    最后說說Vue2 SSR 的 Cookies 問題

    這篇文章主要介紹了最后說說Vue2 SSR 的 Cookies 問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • Vue實(shí)現(xiàn)移動(dòng)端左右滑動(dòng)效果的方法

    Vue實(shí)現(xiàn)移動(dòng)端左右滑動(dòng)效果的方法

    最近得到一個(gè)新需求,需要在Vue項(xiàng)目的移動(dòng)端頁面上加上左右滑動(dòng)效果,經(jīng)過一番折騰,最終決定四月vue-touch。下面小編把實(shí)現(xiàn)代碼分享給大家,感興趣的朋友一起看看吧
    2018-11-11
  • vue中proxy代理的用法(解決跨域問題)

    vue中proxy代理的用法(解決跨域問題)

    這篇文章主要介紹了vue中的proxy代理的用法(解決跨域問題),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Element中Upload組件上傳功能實(shí)現(xiàn)(圖片和文件的默認(rèn)上傳及自定義上傳)

    Element中Upload組件上傳功能實(shí)現(xiàn)(圖片和文件的默認(rèn)上傳及自定義上傳)

    這篇文章主要介紹了Element中Upload組件上傳功能實(shí)現(xiàn)包括圖片和文件的默認(rèn)上傳及自定義上傳,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-01-01
  • 一文搞懂Vue中watch偵聽器的用法

    一文搞懂Vue中watch偵聽器的用法

    在Vue.js中,您可以使用watch選項(xiàng)來創(chuàng)建偵聽器,以偵聽特定屬性的變化,偵聽器可以在屬性發(fā)生變化時(shí)執(zhí)行相關(guān)的邏輯,本文給大家詳細(xì)講講Vue中watch偵聽器的用法,需要的朋友可以參考下
    2023-11-11
  • vue中計(jì)算屬性computed理解說明包括vue偵聽器,緩存與computed的區(qū)別

    vue中計(jì)算屬性computed理解說明包括vue偵聽器,緩存與computed的區(qū)別

    這篇文章主要介紹了對(duì)vue中計(jì)算屬性computed理解說明包括vue偵聽器,緩存與computed的區(qū)別,需要的朋友可以參考下
    2022-05-05
  • Vue中使用富文本編輯框的實(shí)踐與探索

    Vue中使用富文本編輯框的實(shí)踐與探索

    本文詳細(xì)介紹了如何在Vue項(xiàng)目中集成和使用富文本編輯框,并分享了一些實(shí)踐經(jīng)驗(yàn),介紹了為什么需要富文本編輯框,Vue中常用的富文本編輯器,以及如何安裝、配置和使用Vue-Quill-Editor,本文還提供了一些基本的配置示例,幫助開發(fā)者在實(shí)際項(xiàng)目中根據(jù)需求進(jìn)行更多探索和定制
    2024-10-10
  • Vue 設(shè)置axios請(qǐng)求格式為form-data的操作步驟

    Vue 設(shè)置axios請(qǐng)求格式為form-data的操作步驟

    今天小編就為大家分享一篇Vue 設(shè)置axios請(qǐng)求格式為form-data的操作步驟,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • 淺析 Vue 3.0 的組裝式 API(一)

    淺析 Vue 3.0 的組裝式 API(一)

    這篇文章主要介紹了 Vue 3.0 的組裝式 API的部分資料,幫助大家更好的理解和學(xué)習(xí)vue,感興趣的朋友可以了解下
    2020-08-08

最新評(píng)論