最近我们做了一个cms系统,基于vue + vue-router + vuex
其中有个ImageSelectorDialog的全局对话框,可以供所有组件调用。
使用方式是:在该对话框中选中多个图片,然后点击‘确定’按钮,执行一个回调。
在不同的叶子组件中调用该对话框,点击‘确定’时执行的逻辑是不一样的。
问题是:
将ImageSelectorDialog放到某个父级组件中,在叶子组件中调用时需要这样:
this.$parent.$parent.showImageSelectorDialog(function callback(selectedImgs){
//...
})
这样写的话,代码依赖于组件树的层级关系,不太好。
并且ImageSelectorDialog不方便放到根组件中,无法使用this.$root.showImageSelectorDialog(...)的方式调用.
vue中并未提供诸如组件查找的api, 不容易找到ImageSelectorDialog所处的组件实例。
2.将ImageSelectorDialog放到某个父级组件中,其显示的控制 isShowImageSelectorDialog 放到 vuex store中管理, 但问题是不同的使用场景的callback是不一样的, 这个callback function放到vuex store是不合适的.
3.实例化一个全局事件监听对象 watcher = new Vue(). 将ImageSelectorDialog放到某个父级组件中. 在父级组件mouted后,注册监听。
let imageSelectorCallback = noop;
watcher.$on('showImageSelector', function(callback){
imageSelectorCallback = callback;
});
methods:{
onImageSelectorSubmit(selectedImgs){
imageSelectorCallback(selectedImgs);
}
}
然后在叶子组件中调用时,如下:
watcher.$emit('showImageSelector', function(selectedImgs){
//...
})
感觉这三个办法都不太理想,大家有没有其它的办法? 谢谢!
既然用了 vuex,那么就在 vuex 的 state 里放两个数据,一个是 showImageSelector,另一个是 callback function imageSelected,在 imageSelector 里 watch showImageSelector 来显示/隐藏对话框,并且把显示之后的回调设置为 imageSelected。
当需要显示该对话框时,设置 showImageSelector 为 true,并且同时设置 imageSelected 为当前回调函数。