封装弹窗/抽屉,使用hook函数形式减少template内部代码
Posted shellingfordly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了封装弹窗/抽屉,使用hook函数形式减少template内部代码相关的知识,希望对你有一定的参考价值。
hook形式使用弹窗组件
vue3新增了composition api之后,组件功能的拆分更加方便了,下面使用这种方式来编写弹窗组件,抽屉同理。
MyDrawer.vue
首先,自定义一个dialog组件。此组件内部暴露控制弹窗显隐的方法、和设置属性的方法,getCurrentInstance是vue提供的获取组件实例的方法,具体代码如下———
<template>
<el-dialog
:before-close="()=>{ actionDialog(false) }"
v-model="visible"
v-bind="getProps"
>
<template #[item]="data" v-for="item in Object.keys($slots, \'default\')">
<slot :name="item" v-bind="data"></slot>
</template>
</el-dialog>
</template>
<script lang="ts">
import {
computed,
defineComponent,
getCurrentInstance,
reactive,
ref,
} from "vue";
export default defineComponent({
name: "",
setup(props, { emit }) {
const visible = ref(false);
const propsRef = reactive({
visible: false,
title: undefined,
});
const getProps = computed(() => {
return Object.assign(propsRef, props);
});
const dialogInstance = {
actionDialog,
setProps,
};
const instance = getCurrentInstance();
if (instance) {
emit("register", dialogInstance);
}
function actionDialog(isShow: boolean) {
visible.value = isShow;
}
function setProps(propsValue: any) {
Object.assign(propsRef || {}, propsValue);
}
return {
visible,
getProps,
actionDialog,
};
},
});
</script>
useDialog.ts
除了自定义组件内部需要做一些处理之外,还需要提供一个暴露一些操作弹窗方法的useDialog方法,这就是常说的hook函数吧。此处暴露一个register方法,在使用时该方法需要绑定在自定义dialog组件上。当创建了dialog组件后,就会触发register方法,将dialog实例和内部提供的方法传递出来,然后在父组件中使用。
import { ref, unref } from \'@vue/reactivity\'
import { isInSetup } from \'/@/utils/help/vue\'
import { DialogPropsModel, ResultModel, MethodsModel } from "./types";
export function useDialog(props?: DialogPropsModel): ResultModel {
// 监测是否在setup里面调用
isInSetup()
const instanceRef = ref()
const uuidRef = ref()
function register(dialogInstance: any, uuid: string) {
instanceRef.value = dialogInstance
uuidRef.value = uuid
props && methods.setProps(props)
}
const getInstance = () => {
const instance = unref(instanceRef);
if (!instance) {
console.error(\'useModal instance is undefined!\');
}
return instance;
};
const methods: MethodsModel = {
actionDialog(open = true) {
getInstance()?.actionDialog(open)
},
setProps(props: any) {
getInstance()?.setProps(props)
}
}
return [register, methods]
}
home.vue
具体使用时,在父组件中调用对应的TestDialog组件,然后使用useDialog函数暴露出register注册函数和actionDialog操作显隐的函数,将register绑定到TestDialog上,这样当组件被创建时,就会触发emit暴露方法再通过useDialog返回出来,也就是actionDialog函数,绑定对应的触发Dom上就OK了。
<template>
<div>
<el-button @click="actionDialog()">open dialog</el-button>
<TestDialog @register="register" />
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { userStore } from "/@/store/modules/user";
import TestDialog from "/@/components/TestDialog.vue";
import { useDialog } from "/@/components/dialog/useDialog";
export default defineComponent({
components: { MyDrawer },
setup() {
const [register, { actionDialog }] = useDialog({ title: "Dialog" });
return {
register,
actionDialog,
};
},
});
</script>
TestDialog.vue
TestDialog组件中只需要调用MyDialog并使用v-bind="$attrs"将所有的属性和事件传递给MyDialog就可以了。然后就可以在MyDialog中编写弹窗内显示的内容。弹窗的属性可以通过useDialog传递,也可以直接在TestDialog中编写。
<template>
<MyDialog v-bind="$attrs">
这是弹窗内部的内容!
</MyDialog>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import MyDialog from "/@/components/dialog/MyDialog.vue";
export default defineComponent({
name: "TestDrawer",
components: { MyDialog },
setup() {
return {};
},
});
</script>
弹窗代码的拆解,hook形式的代码就完成了。实现了设置dialog属性和设置显示隐藏的简单功能。这样拆解之后,减少了Home组件内部弹窗的template代码,可以随意的将属性在js中或者子组件中进行设置。虽然功能不复杂,但编写起来舒服了很多,否则Home组件中调用element原生的dialog组件的话,需要在template传递很多属性。如果直接抽离的话又需要在子组件中监听显隐变量,父组件监听显隐事件,写了很多与数据不相关的代码,代码看起来也不那么请爽。
以上是关于封装弹窗/抽屉,使用hook函数形式减少template内部代码的主要内容,如果未能解决你的问题,请参考以下文章
Vue3 Composition API——生命周期钩子Provide函数 和 Inject函数封装Hook案例setup顶层编写方式