element-plus弹窗二次封装踩坑
1 基于element-plus的二次封装弹窗很常见。代码如下:
父组件:
import Dialog from './components/Dialogs/testDailog.vue'
const show=ref(false)
const openDialog=()=>{
show.value=true
}
<button @click="openDialog" >打开dialoag</button>
<Dialog v-model="show"/>
弹窗的内容:
<template>
<el-dialog
v-model="visible"
title="Tips"
width="30%"
@close="handerClose"
>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<el-button @click="cancel">取消</el-button>
<el-button @click="confirm">确定</el-button>
</el-dialog>
</template>
<script setup lang='ts'>
import { ref, reactive, watch, onMounted, onUnmounted } from 'vue'
const emits=defineEmits(['close','confirm','update:modelValue'])
const props=defineProps({
modelValue:{
type:Boolean,
default:false
}
})
const visible=ref(false)
const cancel=()=>{
emits('update:modelValue',false)
}
const confirm=()=>{
emits('update:modelValue',false)
}
const handerClose=()=>{
console.log("点击关闭按钮");
emits('update:modelValue',false)
}
watch(()=>props.modelValue,(newVal)=>{
visible.value=newVal;
console.log("props.modelValue",props.modelValue);
emits('update:modelValue',newVal)
})
</script>
<style lang='scss' scoped>
</style>
到这基本上就可以实现了。这一版的特点就是弹窗的关闭时其实本身没有销毁。我们是通过双向绑定跟新了弹窗的状态
但是我们考虑一个场景,就是表单弹窗复用。新增和编辑态我们要做区分。这时候我们手动传属性标识是编辑还是新增就很麻烦。有一个简单的办法就是我们在关闭弹窗时直接把它销毁,这样每次我们只需要在生命周期的onMounted中判断是否有id传过来就可以了。如果有id则说明是编辑态。否则是新增的场景。这样就很容易区分。我们改造下代码:
改进版
销毁弹窗我们通过v-if来控制
父组件
<button @click="openDialog" >打开dialoag</button>
<Dialog v-if="show" v-model="show"/>
//注意这里增加了v-if
弹窗组件
<template>
<el-dialog
v-model="visible"
title="Tips"
width="30%"
@close="handerClose"
>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<P>This is a message</P>
<el-button @click="cancel">取消</el-button>
<el-button @click="confirm">确定</el-button>
</el-dialog>
</template>
<script setup lang='ts'>
import { ref, reactive, watch, onMounted, onUnmounted } from 'vue'
const emits=defineEmits(['close','confirm','update:modelValue'])
const props=defineProps({
modelValue:{
type:Boolean,
default:false
}
})
const visible=ref(props.modelValue)
const cancel=()=>{
emits('update:modelValue',false)
}
const confirm=()=>{
emits('update:modelValue',false)
}
const handerClose=()=>{
console.log("点击关闭按钮");
emits('update:modelValue',false)
}
onMounted(()=>{
console.log("挂载");
})
onUnmounted(()=>{
console.log("卸载");
})
watch(()=>props.modelValue,(newVal)=>{
visible.value=newVal;
console.log("props.modelValue",props.modelValue);
emits('update:modelValue',newVal)
})
</script>
<style lang='scss' scoped>
</style>
在组件内部,我们通过定义visible,初始状态和props.modelValue绑定,后续跟新在watch里同步,这样就可以实现每次销毁和挂载
注意:
const visible=ref(props.modalValue),定义visible的时候一定要先和props.modalValue进行绑定。不然父组件点击不会弹出来