分类
- props和$emit
- 自定义事件
- $attrs
- $parent
- $refs
- provide/inject
- Vuex
不同场景
- 父子组件
- 上下级组件(跨多级)通讯
- 全局组件
代码演示
1. props $emit
父组件:
子组件:
2. 自定义事件方式(适合不相关的组件通讯)
父组件:
子组件1 :CustomEvent1
子组件2 :CustomEvent2
event.js:
3. $attrs (props和emit的候补)
vue3 移除了 listeners 合并到了 $attrs)
level1:
<template>
<p>level1</p>
<Level2
:a="a"
:b="b"
:c="c"
@getA="getA"
@getB="getB"
@getC="getC"
></Level2>
</template>
<script>
import Level2 from './Level2.vue'
export default {
name: 'Level1',
components: {
Level2,
},
data() {
return {
a: 'aaa',
b: 'bbb',
c: 'ccc',
}
},
methods: {
getA() {
return this.a
},
getB() {
return this.b
},
getC() {
return this.c
},
},
}
</script>
level2:
<template>
<p>level2</p>
<Level3 :x="x" :y="y" :z="z" @getX="getX" @getY="getY" @getZ="getZ" v-bind="$attrs"></Level3>
</template>
<script>
import Level3 from './Level3.vue'
export default {
name: 'Level2',
components: {
Level3,
},
props: ['a'], // vue2.x $attrs
emits: ['getA'], // vue2.x $listeners vue3 中 合并到attrs中
data() {
return {
x: 'xxx',
y: 'yyy',
z: 'zzz',
}
},
methods: {
getX() {
return this.x
},
getY() {
return this.y
},
getZ() {
return this.z
},
},
created() {
console.log('level2:',Object.keys(this.$attrs)) // 是 props 和 emits 的候补
},
}
</script>
level3:
<template>
<p>level3</p>
</template>
<script>
export default {
name: 'level3',
props: ['x'],
emits: ['getX'],
inheritAttrs:false,
data() {
return {}
},
created() {
console.log('level3:', Object.keys(this.$attrs))
},
}
</script>
打印的结果:
4. $parent 直接获取父组件
level3:
<template>
<p>level3</p>
</template>
<script>
export default {
name: 'level3',
props: ['x'],
emits: ['getX'],
inheritAttrs:false,
data() {
return {}
},
created() {
// console.log('level3:', Object.keys(this.$attrs))
},
mounted() {
console.log('level3的parent level2:',this.$parent);
}
}
</script>
结果:拥有level2中所有的属性和方法
5. refs 直接获取子组件
level3组件:
<template>
<p>level3</p>
<HelloWorld msg="hello jackson" ref="hello1"></HelloWorld>
</template>
<script>
import HelloWorld from './HelloWorld.vue'
export default {
components: {
HelloWorld
},
name: 'level3',
props: ['x'],
emits: ['getX'],
inheritAttrs:false,
data() {
return {}
},
created() {
// console.log('level3:', Object.keys(this.$attrs))
},
mounted() {
// console.log('level3的parent level2:', this.$parent);
console.log(this.$refs.hello1.name); // 只能在mounted中获取,不能在created中获取,因为created组件树还没完全渲染完成
}
}
</script>
HelloWorld组件:
<template>
<div>
<h1 @click="clickHandler">{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'hello world',
props: {
msg: String,
},
emits: ['showMsg'],
data() {
return {
name:'hello-world'
}
},
methods: {
clickHandler() {
this.$emit('showMsg','hello world')
}
}
}
</script>
结果:
6. provide inject 完美的多层级透传
level1组件:
<template>
<p>level1: <input v-model="name"></p>
<Level2></Level2>
</template>
<script>
import Level2 from './Level2.vue'
import { computed} from 'vue'
export default {
name: 'Level1',
components: {
Level2
},
data() {
return {
name:'jackson'
}
},
// provide: {
// info:'aaa' //静态数据传输方法
// }
provide() {
return {
info:computed(()=>this.name) // 响应式数据
}
}
}
</script>
level2组件:
<template>
<p>level2 {{ info }}</p>
<Level3></Level3>
</template>
<script>
import Level3 from './Level3.vue'
export default {
name: 'Level2',
components: {
Level3
},
inject:['info'],
data() {
return {}
}
}
</script>
level3组件:
<template>
<p>level3: {{ info }}</p>
</template>
<script>
export default {
name: 'Level3',
components: {
},
inject:['info'],
data() {
return {}
}
}
</script>
结果: