关于vue中实现全局单体组件最佳实践的问题

最近我们做了一个cms系统,基于vue + vue-router + vuex

其中有个ImageSelectorDialog的全局对话框,可以供所有组件调用。
使用方式是:在该对话框中选中多个图片,然后点击‘确定’按钮,执行一个回调。
在不同的叶子组件中调用该对话框,点击‘确定’时执行的逻辑是不一样的。

问题是:

  1. 将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){
    //...
})

感觉这三个办法都不太理想,大家有没有其它的办法? 谢谢!

阅读 4.6k
3 个回答

既然用了 vuex,那么就在 vuex 的 state 里放两个数据,一个是 showImageSelector,另一个是 callback function imageSelected,在 imageSelector 里 watch showImageSelector 来显示/隐藏对话框,并且把显示之后的回调设置为 imageSelected。
当需要显示该对话框时,设置 showImageSelector 为 true,并且同时设置 imageSelected 为当前回调函数。

看了一下,可惜我并没有实现过类似的需求,一时半会也不知道该怎么解决
不过不久前就在segmentfault上看到一篇文章或许可以帮到你
https://segmentfault.com/a/1190000007694540
这篇文章里面的隐式创建 Vue 实例章节或许可以给你一点灵感

为什么不能把ImageSelectorDialog放到根组件中?把它放到根组件中,当子组件调用需要现实对话框时,emit一个事件把需要的回调函数当参数传进去就好了啊(this.$emit('showModal', callBack)),然后根组件监听这个showModal事件就可以了啊

推荐问题