最近项目中使用到vue,自己第一次接触这种数据驱动的前端框架,在使用中遇到了一个问题,在这里记下来,希望自己以后不要再犯。也希望可以帮到遇到同样问题的朋友。
vue组件
vue强大的组件系统,对代码的复用和程序的清晰度很有帮助,我们可以将公用的功能抽出来,写成一个vue的组件,以便日后复用,像分页栏、动态导航之类的。
比如所我将列表数据展示和列表的导航分开为两个组件。当我只有一种类型的数据要展示的时候,我就可以直接将列表数据组件拿来用;当我有多种相似的数据类型要展示,这时候就可以结合二者了。
但是怎么结合呢?我说的相似的数据类型指的是同一种数据格式,但是数据来源不同(语文学的不好,请理解🙈),就像图中的分组1、分组2、分组3,不通的列表导航对应着不同的api地址,当点击导航栏的时候,获取对应的接口地址,请求服务器数据,列表展示数据。
事件总线的使用
约定:以下我们将上图中左边的导航栏组件简称为A组件,右边列表组件简称为B组件。
我是这样使用事件总线的,点击A组件当中的导航项,获取对应的请求地址,在事件总线中请求服务器的数据,然后将更新数据,B组件中监控事件总线中的数据,这样就能实现实时刷新了。这其中遇到了一个问题,纠结了我好久。
最开始的事件总线的代码如下(省略了部分代码):
// event bus definition
var bus = new Vue({
data: {
apiUrl: '',
navItems: [
{name: 'group 1', url: 'http://xxxxxx'},
{name: 'group 2', url: 'http://bbbbxx'}
],
dataList: []
},
methods: {
getResponseData: function () {
// 请求服务器数据获取到data后
this.dataList = data;
},
changeApiUrl: function (index) {
this.apiUrl = this.navItems[index].url;
this.getResponseData();
}
},
created: function () {
this.$on('getResponseData', this.getResponseData);
this.$on('changeApiUrl', this.changeApiUrl);
},
beforeDestroy: function () {
this.$off('getResponseData', this.getResponseData);
this.$off('changeApiUrl', this.changeApiUrl);
}
});
// 导航组件 A
var navItemComponent = {
data: function () {
return {
navItems: bus.navItems
}
},
methods: {
onItemClick: function (index) {
bus.$emit('changeApiUrl', index);
}
}
};
// 列表组件 B
var tableList = {
data: function () {
return {
dataList: bus.dataList
}
}
};
这种情况页面正常渲染没有问题,但是当我点击不同的导航栏的时候,列表中没有数据显示,查看http响应报文,可以看到响应的数据,为什么不显示呢?
问题出现在下面这两个片段的代码:
//事件总线中
getResponseData: function () {
// 请求服务器数据获取到data后
this.dataList = data;
}
// 列表组件中
data: function () {
return {
dataList: bus.dataList
}
}
这相当于什么呢?下面这个例子很好的说清楚了。
var a = 'hello world';
var b = a;
var c = 'babababa';
var a = c;
// 这种情况下:
console.log(a); // output: babababa
console.log(b); // output: hello world
console.log(c); // output: babababa
那怎么解决呢?请求获取完数据后,不要改变事件总线中dataList的引用对象就好了。
getResponseData: function () {
// 请求服务器数据获取到data后
this.dataList.splice(0,this.dataList.length);
for(var i = 0;i<this.data.length;++i){
this.dataList.push(data[i]);
}
}
这是我想到的解决办法,如果你看了这篇文章,有更好的解决办法的话,能告诉我吗?