start
- 最近在学习 vue3,在学习 vue3 的 之前。先总结一下,vue2 中的组件之间的通信;
以下示例皆为 vue2
1.父组件传值给子组件,利用 props
父组件 app.vue
<template>
<div id="app">
<boxA :name="appName" :age="appAge" />
</div>
</template>
<script>
import boxA from './boxA.vue'
export default {
name: 'App',
data() {
return {
appName: '我是app页面的name',
appAge: '我是app页面的age 123',
}
},
components: {
boxA,
},
}
</script>
子组件 boxA.vue
<template>
<div class="box">
我是 A盒子
<pre>
我有这些属性:
{{ name }}
</pre>
</div>
</template>
<script>
export default {
name: 'boxA',
props: {
name: {
type: String, // 限制类型
default: '', // 设置默认值
require: true, // 是否必传
},
},
}
</script>
2.子组件和父组件通信 $emit
父组件 app.vue
<template>
<div id="app">
主应用
<boxA @say="sayApp" />
</div>
</template>
<script>
import boxA from './boxA.vue'
export default {
name: 'App',
components: {
boxA,
},
methods: {
sayApp(value) {
console.log('hello', value)
},
},
}
</script>
子组件 boxA.vue
<template>
<div class="box">
<span @click="handleClick">你好</span>
</div>
</template>
<script>
export default {
name: 'boxA',
methods: {
handleClick() {
this.$emit('say', '输出的参数')
},
},
}
</script>
3. 跨多级组件通信
/*新建一个Vue实例作为中央事件总线*/
let event = new Vue()
/*监听事件*/
event.$on('eventName', (val) => {
//......do something
})
/*触发事件*/
event.$emit('eventName', 'this is a message.')
4.跨多级组件数据通信
vuex4.
5. 父-》子-》孙 三个层级之间的组件通信 $attrs
$listeners
有这么一个场景,组件 A 中有组件 B,组件 B 中有 C。AC 之间通信怎么办?
- 使用父子通信,B 组件中会有很多冗余代码。
- 使用事件总线,不太利于管理;
- 使用 vuex,有点大材小用;
在 vue2.4 版本之后,添加了这么几个属性:
$attrs
$listeners
$attrs
- vm 上的属性。所以我们可以直接在组件中,
this.$attrs
打印出来; - 2.4.0 新增的属性;
- 简单理解就是一个对象。所有父组件传递给子组件的值,当子组件没有用 prop 属性接收,就会存储在
this.$attrs
中。(class 和 style 除外)
$listeners
- vm 上的属性。所以我们可以直接在组件中,
this.$listeners
打印出来; - 2.4.0 新增的属性;
- 简单理解就是一个对象。所有父组件给子组件绑定到事件会存储在
this.$listeners
中,(不含 .native 修饰器的)
有什么用?
想象我们的场景:
- A 组件和 C 组件通信;
- A 传递数据给 B,绑定事件到 B 上。
- 可以在 B 中通过
this.$attrs
和this.$listeners
拿到数据和事件 - 一起传递给 C 组件。
例如:
父组件 app.vue
<template>
<div id="app">
<boxA :name="appName" :age="appAge" @fn1="appFn1" @fn2="appFn2" />
</div>
</template>
<script>
import boxA from './boxA.vue'
export default {
name: 'App',
data() {
return {
appName: '我是app页面的name',
appAge: '我是app页面的age 123',
}
},
components: {
boxA,
},
methods: {
appFn1(value) {
console.log('appFn1', value)
},
appFn2(value) {
console.log('appFn2', value)
},
},
}
</script>
子组件 boxA.vue
<template>
<div class="box">
我是 A盒子
<pre>
我有这些属性:
{{ name }}
</pre>
<!-- !!!这里可以再来一个组件 boxB; 通过 v-bind="$attrs" v-on="$listeners" 就能在boxB中收到数据了-->
<!-- <boxB v-bind="$attrs" v-on="$listeners"> -->
</div>
</template>
<script>
export default {
name: 'boxA',
inheritAttrs: false,
props: {
name: {
type: String, // 限制类型
default: '', // 设置默认值
require: true, // 是否必传
},
},
created() {
console.log(this)
this.$emit('fn1', '触发父组件第一个函数')
},
}
</script>
另外说个其他的小 tips
- 没有被 父组件传递给子组件的值,如果没有被 props 接受。 默认会展示在 html 的标签上
可使用
inheritAttrs: false,
隐藏