最近的公司开发任务中,遇到了要自己封装弹窗组件的需求,于是就撸了一个... 领导希望这个方法满足以下条件:
支持懒加载(异步加载函数)
props传参
事件绑定
provide inject 注入数据
各种自定义插槽
暴露内部方法
下面是一个满足您要求的 Vue 3 函数式弹窗组件的实现示例。这个弹窗组件支持懒加载、props 传参、事件绑定、provide/inject 注入数据、各种自定义插槽,并且暴露内部方法。
1. 创建弹窗组件
首先,创建一个名为 Modal.vue 的组件:
<div v-if="isVisible" class="modal-overlay">
<div class="modal">
<h2>{{ title }}</h2>
<div class="modal-content">
<slot name="header"></slot> <!-- 自定义头部插槽 -->
<slot></slot> <!-- 默认插槽 -->
<slot name="footer"></slot> <!-- 自定义底部插槽 -->
</div>
<button @click="close">关闭</button>
</div>
</div>
</template>
<script>
import { ref, watch, provide, inject } from 'vue';
export default {
name: 'Modal',
props: {
title: {
type: String,
default: '弹窗标题',
},
visible: {
type: Boolean,
default: false,
},
},
setup(props, { emit }) {
const isVisible = ref(props.visible);
// 提供内部方法
const close = () => {
isVisible.value = false;
emit('update:visible', false);
};
// 监听 visible 属性的变化
watch(() => props.visible, (newVal) => {
isVisible.value = newVal;
});
// Provide inject example
const modalData = { close };
provide('modalData', modalData);
return {
isVisible,
close,
};
},
};
</script>
<style scoped>
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.modal {
background: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style>
2. 创建弹窗控制函数
接下来,创建一个函数来控制弹窗的显示。可以在 src/utils/modal.js 中实现:
import Modal from '../components/Modal.vue';
const modalInstance = {
app: null,
instance: null,
};
const showModal = async (title, props = {}, slots = {}) => {
if (!modalInstance.app) {
// 懒加载 Modal 组件
const { default: Modal } = await import('../components/Modal.vue');
modalInstance.app = createApp({
setup() {
const isVisible = ref(true);
const close = () => {
isVisible.value = false;
setTimeout(() => {
modalInstance.app.unmount();
modalInstance.app = null;
}, 300); // 等待动画结束后卸载
};
return () => h(Modal, {
title,
visible: isVisible.value,
'onUpdate:visible': close,
...props, // 传递 props
}, slots); // 传递插槽
},
});
modalInstance.instance = modalInstance.app.mount(document.createElement('div'));
document.body.appendChild(modalInstance.instance.$el);
}
};
export { showModal };
3. 使用弹窗
在你的 Vue 组件中,可以通过调用 showModal 函数来显示弹窗,并传递 props 和插槽内容。例如:
<div>
<button @click="openModal">打开弹窗</button>
</div>
</template>
<script>
import { showModal } from '../utils/modal';
export default {
name: 'App',
methods: {
openModal() {
showModal('欢迎', { someProp: 'someValue' }, {
header: () => <div>自定义头部内容</div>,
default: () => <div>这是弹窗的主体内容!</div>,
footer: () => <div>自定义底部内容</div>,
});
},
},
};
</script>
4. 总结
以上代码实现了一个支持懒加载、props 传参、事件绑定、provide/inject 注入数据、各种自定义插槽,并且暴露内部方法的 Vue 3 函数式弹窗组件。用户可以通过调用 showModal 函数来打开弹窗,并传递自定义内容作为插槽。你可以根据需要进一步扩展这个弹窗组件,例如添加更多的样式、动画效果或其他功能。