千家信息网

怎么封装一个更易用的Dialog组件

发表于:2025-01-16 作者:千家信息网编辑
千家信息网最后更新 2025年01月16日,这篇"怎么封装一个更易用的Dialog组件"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这
千家信息网最后更新 2025年01月16日怎么封装一个更易用的Dialog组件

这篇"怎么封装一个更易用的Dialog组件"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"怎么封装一个更易用的Dialog组件"文章吧。

    场景

    在项目中,我们经常会遇到使用弹窗的场景,但有时组件库自带的弹窗不能满足我们的需求,需要我们自己封装,这时我们如何去自定义一个更加方便调用的弹窗?

    搭建环境

    首先我们需要搭建一个Vue3+ts的环境。

    用vite的官方模板:

    yarn create vite demo-app --template vue-ts

    进入并安装依赖

    cd demo-appyarn

    依赖安装完成后启动app

    yarn dev

    创建组件

    先在src/components目录下创建MyDialog.vue,搭建一个组件的基本框架

    创建调用组件的hook函数

    在src目录下创建hooks目录,然后再hooks目录下创建useMyDialog.ts.

    函数调用组件我们需要:

    • 将组件转换成VNode

    • 将VNode转换成DOM然后渲染到页面

    import { createVNode, render, ComponentPublicInstance } from "vue";export default function useMyDialog(option?: any) {  const props = {    ...option,  };  const vm = createVNode(MyDialog, props);  const container = document.createElement("div");  render(vm, container);  document.querySelector("#app")?.appendChild(container.firstElementChild!);}

    ps:

    container.firstElementChild!中的!表示container.firstElementChild不为null或者undefined

    接下来我们在App.vue中测试一下

    Dialog的缓存、隐藏

    隐藏

    我们需要将close返回出去,这样我们就可以手动调用close函数关闭Dialog.

    在useMyDialog.ts中添加

    import { ComponentPublicInstance,VNode } from "vue";export default function useMyDialog(option?: any) {  const userCloseFn = option?.onClose;  props.onClose = () => {    close();    userCloseFn ?? userCloseFn();  };  function close(vm: VNode) {    (      vm.component!.proxy as ComponentPublicInstance<{ visible: boolean }>    ).visible = false;  }  return {    close: close.bind(null, vm),  }}

    缓存

    现在每次点击显示Dialog按钮时都会创建一个新的组件实例,这不是我们的预期,所以我们需要将组件进行缓存.

    在useMyDialog.ts中添加

    import { ComponentPublicInstance } from 'vue'const instances: any[] = [];export default function useMyDialog(option?: any) {  const tempVm: any = instances.find(    (item) =>      `${item.vm.props?.message ?? ""}` === `${(option as any).message ?? ""}`  );  if (tempVm) {    (      tempVm.vm.component!.proxy as ComponentPublicInstance<{        visible: boolean;      }>    ).visible = true;    return {      close: close.bind(null, tempVm.vm),    };  }}

    完整代码

    src/hooks/useMyDialog.ts

    import { createVNode, render, ComponentPublicInstance, VNode } from "vue";import MyDialog from "../components/MyDialog.vue";const instances: any[] = [];export default function useMyDialog(option?: any) {  const props = {    ...option,  };  const userCloseFn = option?.onClose;  props.onClose = () => {    close(vm);    userCloseFn ?? userCloseFn();  };  function close(vm: VNode) {    (      vm.component!.proxy as ComponentPublicInstance<{ visible: boolean }>    ).visible = false;  }  const tempVm: any = instances.find(    (item) =>      `${item.vm.props?.message ?? ""}` === `${(option as any).message ?? ""}`  );  if (tempVm) {    (      tempVm.vm.component!.proxy as ComponentPublicInstance<{        visible: boolean;      }>    ).visible = true;    return {      close: close.bind(null, tempVm.vm),    };  }  const vm = createVNode(MyDialog, props);  const container = document.createElement("div");  render(vm, container);  document.querySelector("#app")?.appendChild(container.firstElementChild!);  instances.push({ vm });  return {    close: close.bind(null, vm),  };}

    以上就是关于"怎么封装一个更易用的Dialog组件"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。

    0