现实中的许多Web应用都有许多弹框,或者交互事件的开发需求。博主曾开发过较大型的Vue Web
应用,光控制这些弹框的显示隐藏都感觉恶心:初始化isDialogShow=false
,点击按钮isDialogShow=true
,弹框显示后点击确认、取消和关闭按钮需要广播事件或者通过$parent将父组件的isDialogShow
置为false
。还有就是跨组件的事件广播也让人头大。如若弹框比较多或者跨组件事件较多,采用生硬的控制显得很不优雅。
福音来了,如若你的Vue
应用已经自带vuex
或者应用交互过多需要引入vuex
,那么下面的方案将是个不错的解决方案。先说一下用vuex
统一管理弹框和事件优点:统一控制,一目了然、控制简单。其相关概念可查看vuex,这里就不赘述了。
-
初始化state
state: { // 弹框信息显示控制标识统一定义于此,统一管理 BooleanFlag: { //小驼峰:is 名词 动词 isDemoDialogShow: false, // demo 弹框显示 }, // 事件直通车, 相关事件可以统一管理 EventBus: { Page1ToPage2: {}, // 采用对象是为了传递数据 } }
-
定义mutations
mutations: { // 自动取反 BooleanFlag(state, flagKeys) { if (!Array.isArray(flagKeys)) return const BooleanFlag = state.BooleanFlag flagKeys.forEach(flagKey => BooleanFlag[flagKey] = !BooleanFlag[flagKey]) }, // EventBus EventBus(state, eventWithData={}) { const EventBus = state.EventBus Object.keys(eventWithData).forEach(eventKey=>{ if(EventBus[eventKey] !== undefined){ EventBus[eventKey] = eventWithData[eventKey] } }) } }
-
父组件应用
<template> <div> <div class="button-bar"> <el-button @click="onDialogShow" type="primary">打开弹框</el-button> <el-button @click="onEmitData" type="primary">广播数据</el-button> </div> <div> <demo-dialog v-if="BooleanFlag.isDemoDialogShow"></demo-dialog> </div> </div> </template> <script> import { mapState } from "vuex"; import DemoDialog from "@/dialogs/DemoDialog"; export default { components: { DemoDialog }, computed: mapState(["BooleanFlag"]), methods: { // 弹框Demo onDialogShow() { this.$store.commit("BooleanFlag", ["isDemoDialogShow"]); }, // 广播事件 onEmitData() { const messageObj = { message: "from page1" }; this.$store.commit("EventBus", { Page1ToPage2: messageObj }); } } };
-
弹框组件的应用
<template> <div> <el-dialog :title="title" :visible.sync="isShow" :width="width" custom-class="ht-dialog" :before-close="onCancle"> <div class="dialog-container"> 弹框内容 </div> <div class="bottom-buttons"> <el-button @click="onCancle">{{$t('Common.cancel')}}</el-button> <el-button type="primary" @click="onSure">{{$t('Common.sure')}}</el-button> </div> </el-dialog> </div> </template> <script> export default { name: "DemoDialog", data() { return { title: "弹框标题", width: "500px", isShow: true }; }, methods: { onSure() { // 业务代码 this.onCancle() }, onCancle() { // 关闭弹框 this.$store.commit("BooleanFlag", ["isDemoDialogShow"]); } } }; </script>
-
兄弟页面的应用(响应事件)
注意这里要配合 来使用,采用监听数据变化的方式来响应事件。
<template>
<div>
page2下的内容
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: mapState(["EventBus"]),
watch: {
"EventBus.Page1ToPage2": function(message) {
console.log("Page1ToPage2", message);
}
}
};
</script>