封装一:只把弹窗封装成一个单独的组件
1. 弹窗组件 my-dialog.vue
<template>
<el-dialog title="选择水果" :visible.sync="dialogVisible" width="30%">
<div>弹窗内容</div>
<span slot="footer">
<el-button @click="toggleDialog('dialogVisible', false)">取 消</el-button>
<el-button type="primary" @click="handleOk">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
props: {
visible: Boolean,
},
data() {
return {};
},
computed: {
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit('update:visible', val);
},
},
},
methods: {
toggleDialog(key, visible) {
this[key] = visible;
},
handleOk() {},
},
};
</script>
<style lang="less" scoped>
</style>
2. 点击按钮所在的业务组件
<template>
<div>
<el-button type="primary" @click="visible = true">显示弹窗</el-button>
<MyDialog v-if="visible" :visible.sync="visible"/>
</div>
</template>
优点:弹窗组件上加v-if,只有弹窗显示的时候才会去执行弹窗组件里的生命周期,而且每次弹窗显示都会执行一般完整的组件生命周期,就不用手动去初始化之前缓存的数据了。
缺点:按钮和弹窗的显示、隐藏功能会跟业务代码耦合在一起,解耦不彻底。
封装二:按钮 + 弹窗 封装在一个组件里
1. 按钮 + 弹窗组件 show-dialog-btn.vue
<template>
<div style="display: inline-block">
<slot :show="show"></slot>
<el-dialog
title="选择水果"
:visible.sync="dialogVisible"
width="30%"
>
<el-checkbox-group v-model="checkList">
<el-checkbox
v-for="it in optionList"
:key="it.value"
:label="it.value"
>{{it.text}}</el-checkbox>
</el-checkbox-group>
<span slot="footer">
<el-button @click="toggleDialog('dialogVisible', false)">取 消</el-button>
<el-button type="primary" @click="">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data () {
return {
...this.getInitialData(),
dialogVisible: false,
};
},
created () {
this.init();
},
methods: {
init() {
this.optionList = [
{ value: 'apple', text: '苹果' },
{ value: 'orange', text: '橘子' },
{ value: 'pear', text: '梨' },
];
},
show() {
this.toggleDialog('dialogVisible', true);
},
toggleDialog(key, visible) {
this[key] = visible;
},
// 获取需要初始化的数据
getInitialData() {
return {
checkList: [],
}
},
},
watch: {
dialogVisible(val) {
if (!val) return;
Object.assign(this, this.getInitialData());
}
},
}
</script>
2. 使用组件
<ShowDialogBtn>
<template #default="{show}">
<a @click="show">显示弹窗</a>
</template>
</ShowDialogBtn>
优点:1. 按钮 + 弹窗的整个组件跟业务组件解耦的比较干净。
2. 按钮通过 slot 传入,看业务代码的时候也很好知道这个是什么按钮。
缺点:1. 要在组件显示或关闭时手动初始化之前的数据。
2. 弹窗还没有显示,就要去执行组件的生命周期,有时候用户并不会去打开弹窗,但也会去执行弹窗里面的生命周期,造成不必要的计算。
还有一种按钮 + 弹窗封装在一起的方法是,按钮不用 slot 传入,而是直接写在组件里面:
<template>
<span>
<a @click="show">显示弹窗</a>
<el-dialog
title="选择水果"
:visible.sync="dialogVisible"
width="30%"
>
<el-checkbox-group v-model="checkList">
<el-checkbox
v-for="it in optionList"
:key="it.value"
:label="it.value"
>{{it.text}}</el-checkbox>
</el-checkbox-group>
<span slot="footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</span>
</template>
<ShowDialogBtn/>
优点:跟业务代码解耦的最彻底。
缺点:1. 一眼看不出这是哪个功能按钮,还要看一下组件里的代码。
2. 要在组件显示或关闭时手动初始化data数据。