最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
封装一个更易用的Dialog组件过程代码解析
时间:2022-06-29 01:47:13 编辑:袖梨 来源:一聚教程网
本篇文章小编给大家分享一下封装一个更易用的Dialog组件过程代码解析,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
场景
在项目中,我们经常会遇到使用弹窗的场景,但有时组件库自带的弹窗不能满足我们的需求,需要我们自己封装,这时我们如何去自定义一个更加方便调用的弹窗?
搭建环境
首先我们需要搭建一个Vue3+ts的环境。
用vite的官方模板:
yarn create vite demo-app --template vue-ts
进入并安装依赖
cd demo-app yarn
依赖安装完成后启动app
yarn dev
创建组件
先在src/components目录下创建MyDialog.vue,搭建一个组件的基本框架
{{ title }}{{ message }}
创建调用组件的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),
};
}
相关文章
- 三国志8重制版虚构特典剧本介绍说明 10-30
- 暗喻幻想暗黑法师解锁方法攻略分享 10-30
- 暗喻幻想元素大师解锁方法攻略分享 10-30
- 暗喻幻想地下纳骨堂锁住的门打开方法 10-30
- 暗喻幻想6月22日玛丽亚位置一览 10-30
- 暗喻幻想巫师阿基态解锁方法分享 10-30

