現實中的許多Web應用都有許多彈框,或者交互事件的開發需求。博主曾開發過較大型的Vue Web
應用,光控制這些彈框的顯示隱藏都感受噁心:初始化isDialogShow=false
,點擊按鈕isDialogShow=true
,彈框顯示後點擊確認、取消和關閉按鈕須要廣播事件或者經過$parent將父組件的isDialogShow
置爲false
。還有就是跨組件的事件廣播也讓人頭大。如若彈框比較多或者跨組件事件較多,採用生硬的控制顯得很不優雅。javascript
福音來了,如若你的Vue
應用已經自帶vuex
或者應用交互過多須要引入vuex
,那麼下面的方案將是個不錯的解決方案。先說一下用vuex
統一管理彈框和事件優勢:統一控制,一目瞭然、控制簡單。其相關概念可查看vuex,這裏就不贅述了。vue
state: {
// 彈框信息顯示控制標識統必定義於此,統一管理
BooleanFlag: {
//小駝峯:is 名詞 動詞
isDemoDialogShow: false, // demo 彈框顯示
},
// 事件直通車, 相關事件能夠統一管理
EventBus: {
Page1ToPage2: {}, // 採用對象是爲了傳遞數據
}
}
複製代碼
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>
複製代碼
注意這裏要配合 來使用,採用監聽數據變化的方式來響應事件。java
<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>
複製代碼