最近在整理项目中代码,在组件之间数据传递遇到了问题,所以做了这次总结,如有不对的地方,望指正。

父组件如何将数据传到子组件中

父组件可以通过Prop传递数据到子组件中。

这里需要注意的是:

  • Prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。

  • 每次父组件更新时,子组件的所有 Prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop。如果你这么做了,Vue 会在控制台给出警告。

在两种情况下,我们很容易忍不住想去修改 prop 中数据:

  • Prop 作为初始值传入后,子组件想把它当作局部数据来用;

解决方法:定义一个局部变量,并用 prop 的值初始化它:

1
2
3
4
props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}
  • Prop 作为原始数据传入,由子组件处理成其它数据输出。

解决方法: 定义一个计算属性,处理 prop 的值并返回:

1
2
3
4
5
6
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}

PS:上边的内容是vue文档里边有说的,我只是把自己在项目中遇到的问题抽出来了。链接

栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 父组件 index.vue
<template>
<div class="content">
<child :lists="lists"></child>
</div>
</template>
<script>
import child from './child.vue';
export default {
components: {
child
},
data() {
return {
lists: []
};
},
mounted() {
this.lists = [{
name: '01',
content: 'hi,'
}, {
name: '02',
content: 'my name is Ellyliang'
}];
}
};
</script>

// 子组件 child.vue
<template>
<ul class="content">
<li v-for="(list, index) in getLists" :key="index" v-html="list.name + list.content"></li>
</ul>
</template>
<script>
export default {
props: ['lists'],
data() {
return {
getLists: this.lists
};
},
mounted() {
this.getLists.push({
name: '03',
content: '不要在乎内容,我就是测试'
});
}
};
</script>

子组件如何将数据传到父组件中

子组件可通过vm.$emit将数据传递给父组件

vm.$emit是啥

触发当前实例上的事件。附加参数都会传给监听器回调。 链接

栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// 父组件 index.vue
<template>
<div class="content">
<child :lists="lists" @listenToChild="getChildMsg"></child>
</div>
</template>
<script>
import child from './child.vue';
export default {
components: {
child
},
data() {
return {
lists: []
};
},
mounted() {
this.lists = [{
name: '01',
content: 'hi,'
}, {
name: '02',
content: 'my name is Ellyliang'
}];
},
methods: {
getChildMsg(val) {
alert(val); // 'hello'
}
}
};
</script>

// 子组件 child.vue
<template>
<div class="content">
<ul class="lists">
<li v-for="(list, index) in getLists" :key="index" v-html="list.name + list.content"></li>
</ul>
</div>
</template>
<script>
export default {
props: ['lists'],
data() {
return {
getLists: this.lists
};
},
mounted() {
this.getLists.push({
name: '03',
content: '不要在乎内容,我就是测试'
});

setTimeout(() => {
this.$emit('listenToChild', 'hello');
}, 15000);
}
};
</script>

子组件给父组件传数据是不是也很方便。实现方法是就是在子组件中$emit数据,然后在父组件中通过事件@事件名接收值。

Event Bus

事件巴士这种方法,不仅能处理父子组件传递,子父组件传递,还是处理平级组件之间的数值传递。其实现方法就是在全局new一个vue实例,然后传值给bus, 就是let bus = new vue();。通过这个全局的bus中的$emit, $on等等去实现数据的传递。这样处理有个问题,由于event bus处理数据传递很方便,不管在哪里都可以传递,这样导致滥用,从而导致代码很难去理解。

Event Bus实现

1
2
3
4
5
6
7
let bus = new Vue();
// 触发组件 A 中的事件
bus.$emit('id-selected', 1);
// 在组件 B 创建的钩子中监听事件
bus.$on('id-selected', function (id) {
// ...
});

具体组件的封装和使用,可参考vue-bus

除了以上3种方法,还有就是通过vuex去处理数据的传递,但是我还没有接触,大家要感兴趣,自己去学习。