我最近使用Vue.js和Express.js构建了一个小应用程序。服务器需要准备的组件很少,例如Article.Category和Article.User的组合框。需要从服务器呈现这两个组件的选项。我在文章编辑表单中使用<component />
作为这两个组件的占位符:
<component v-bind:is="user_selection_component"></component>
<component v-bind:is="category_selection_component"></component>
我使用模板字符串初始化组件,模板字符串result.data.template
由服务器传递:
let org_data = original_store;
let new_data = () => {
org_data['remote_options'] = result.data.remote_options;
//if there is any default value, then assign the value to field referred by "model_name"
if(model_name && result.data.preset_value){
let previous_value = $shared.index(org_data, model_name);
if(!previous_value){
$shared.index(org_data, model_name, result.data.preset_value);
}
}
return org_data;
}
var default_cb = ()=>{console.info('['+model_name+'].default_cb()')};
let TempComponent = {
template: result.data.template,
methods: component_ref.methods,
data: new_data,
mounted: cb !== null ? cb.bind(this, org_data) : default_cb.bind(this)
};
app[mount_component] = TempComponent;
问题是,data方法为动态加载的组件返回一个新的Observable商店,它们不与父组件共享同一个商店对象,这是文章编辑的。因此,如果我想修改类别字段值或用户字段值,我必须让回调函数cb
接受这两个动态加载组件的商店对象。否则,从父组件中,我无法修改这两个组件中的值。
所以我提出了一个临时解决方法,我将setter方法作为回调函数传递给这些动态加载的函数:
let set_user_id = null;
let set_cate_id = null;
(org_store) => { set_user_id = (new_id) => { org_store.form.user_id = new_id; }}
(org_store) => { set_cate_id = (new_id) => {org_store.form.category_id = new_id; }}
我加载其他组件后或想要设置类别/用户值时,我只需拨打set_user_id($new_user_id)
或set_cate_id($new_category_id)
;
我根本不喜欢这项工作。我尝试使用事件处理程序将新值发送到这两个组件中。但我无法通过$ref
访问这两个动态加载的组件。有没有更好的方法让动态加载的组件之间共享数据?感谢。
答案 0 :(得分:2)
如果您的组件将接受道具,您可以本地化您的事件总线,这比拥有全局更好。父组件将总线创建为数据项:
data() {
...
bus: new Vue()
}
组件接受它作为道具:
<component v-bind:is="user_selection_component" :bus="bus"></component>
<component v-bind:is="category_selection_component" :bus="bus"></component>
并且您在答案中使用它,除了引用this.bus
而不仅仅是bus
。
答案 1 :(得分:1)
我不认为我现在拥有的是最好的解决方案。在与其他人协商后,我将事件总线作为更好的解决方案。所以我修改了我的代码:
在我的init组件中:
let org_data = original_store;
let new_data = () => {
org_data['remote_options'] = result.data.remote_options;
//if there is any default value, then assign the value to field referred by "model_name"
if(model_name && result.data.preset_value){
let previous_value = $shared.index(org_data, model_name);
if(!previous_value){
$shared.index(org_data, model_name, result.data.preset_value);
}
}
return org_data;
}
var default_cb = () => { console.info('['+model_name+'].default_cb()') };
let TempComponent = {
template: result.data.template,
methods: component_ref.methods,
data: new_data,
mounted: cb !== null ? cb.bind(this, org_data) : default_cb.bind(this)
};
bus.$on('set.' + model_name, function(value){
$shared.index(org_data, model_name, value);
});
区别在于:
bus.$on('set.' + model_name, function(value){
$shared.index(org_data, model_name, value);
});
bus
是由Vue()
创建的公共事件总线:
let bus = new Vue()
从父组件中,我可以使用此事件总线发出事件:
bus.$emit('set.form.user_id', this.form.user_id);
更改此解决方案后,我感觉更好。但是,如果有更好的方法,我仍然感激不尽。感谢。