【Vue组件通信方式】
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
文章目录
前言
组件通信在工作中很常见但通讯的方式很多且使用场景也不同故在此记录和总结。
一、父子组件通信
1、父传子
①使用props
接收父组件传递的属性
// 父组件
<template>
<Helloword :msg=msg />
</template>
<script>
export default {
data() {
return {
msg: 'message'
}
}
}
</script>
// 子组件
<template>
<h1>{{ msg }}</h1>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
}
</script>
② 使用$attrs
接收父组件未在 props
和 emits
中定义的属性和事件
- 父组件level1向level2传递属性a、b、c和事件getA()、getB()、getC()
// level1.vue
<template>
<p>Level1</p>
<Level2
:a="a"
:b="b"
:c="c"
@getA="getA"
@getB="getB"
@getC="getC"
></Level2>
</template>
<script>
import Level2 from './Level2'
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使用
this.$attrs
接收父组件未在props
和emits
中定义的属性和事件
// level2.vue
<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'
export default {
name: 'Level2',
components: { Level3 },
props: ['a'],
emits: ['getA'],
data() {
return {
x: 'xxx',
...
}
},
methods: {
getX() {
return this.x
}
...
},
created() {
console.log('level2', Object.keys(this.$attrs)) // 是 props 和 emits 后补
},
}
</script>
- 子组件level3接收父组件level2中未被
props
和emits
接收的属性和事件。level2组件中定义level3组件时使用v-bind="$attrs"
可接收level1中未在props
和emits
中定义的属性和事件。
<template>
<p>Level3</p>
</template>
<script>
export default {
name: 'Level3',
props: ['x'],
emits: ['getX'],
inheritAttrs: false, // 避免在dom节点中增加传递的属性如<p b='b' c='c'></p>。使用attrs在只有一个根元素时就会生成
created() {
console.log('level3', Object.keys(this.$attrs)) // 是 props 和 emits 候补
}
}
</script>
$attrs
可以实现多级组件传递但是依赖v-bind="$attrs"
。它是 props 和 emits 候补
③使用 $parent
获取父组件的信息
mounted() {
console.log(this.$parent.getX())
},
2、子传父
① 使用 $emit
传递信息给父组件
父组件
<template>
<HelloWorld :getMsg="getMsg"/>
</template>
<script>
export default {
name: 'HelloWorld',
methods: {
getMsg(msg) {
console.log(msg);
}
},
}
子组件
// 子组件:HelloWorld
<template>
<button @click = "clickHandler">传递</button>
</template>
<script>
export default {
name: 'HelloWorld',
// emits: ['showMsg'], // Vue3
methods: {
clickHandler() {
this.$emit('getMsg', 'hello world')
}
},
}
</script>
② 使用$refs
获取子组件的属性和事件
父组件
<template>
<p>Level3</p>
<HelloWorld msg="hello 双越" ref="hello1"/> // 子组件
</template>
<script>
import HelloWorld from '../HelloWorld'
export default {
...
mounted() {
console.log(this.$refs.hello1.name) // created里面组件未渲染完成需要再mounted里面获取
},
}
</script>
二、自定义事件适用于兄弟组件或“距离”较远的组件
兄弟组件1
<template>
<p><button @click="trigger">点击传值</button></p>
</template>
<script>
import event from '../utils/event.js'
export default {
name: 'CustomEvent2',
methods: {
trigger() {
event.emit('showMsg', 'hello custom event') // 触发事件
}
},
}
</script>
// 兄弟组件2
<template>
<p>接收值</p>
</template>
<script>
import event from '../utils/event.js'
export default {
name: 'CustomEvent1',
methods: {
showMsg(msg) {
console.log(msg)
}
},
mounted() {
event.on('showMsg', this.showMsg) //绑定事件
},
// Vue2.x beforeDestroy
beforeUnmount() {
event.off('showMsg', this.showMsg) // 组件销毁需要off事件。否则会造成内存泄漏
},
}
</script>
Vue 版本的区别
- Vue 2.x 可以使用 Vue 实例作为自定义事件
- Vue 3.x 需要使用第三方的自定义事件例如 https://www.npmjs.com/package/event-emitter
自定义事件可能出现多个触发多个绑定所以容易造成项目混乱用的时候要遵守规范。
三、多级组件上下级provide
、inject
传递数据的组件使用provide
传递
<template>
<p>Level1: <input v-model="name"></p>
<Level2></Level2>
</template>
<script>
import { computed } from 'vue'
import Level2 from './Level2'
export default {
name: 'Level1',
components: { Level2 },
data() {
return {
name: 'lisa'
}
},
provide() {
return {
info: computed(() => this.name) // cmputed包裹响应式数据实现下级组件数据响应式
}
}
}
</script>
需要被传递数据的组件使用inject
接收。支持多层或多个组件接收。
<template>
<p>Level2 {{info}}</p>
<Level3></Level3>
</template>
<script>
import Level3 from './Level3'
export default {
name: 'Level2',
components: { Level3 },
inject: ['info']
}
</script>
总结
- 父子组件通讯
props
emits
this.$emit
$attrs
也可以通过v-bind="$attrs"
向下级传递$parent
$refs
- 多级组件上下级
provide
inject
- 跨级、全局
- 自定义事件
- Vuex