目录
- 1、常见通信方式汇总:
- 2、常用组件通信方式说明
- 2.1 【props】
- 2.2【自定义事件】
- 2.3 【v-model】
- 2.4 【$attrs 】
- 2.5 【\$refs、\$parent】
- 2.6 【provide、inject】
1、常见通信方式汇总:
Vue3
组件通信和Vue2
的区别:
- 移出事件总线,使用
mitt
代替。 - 使用
pinia
替换vuex
。 - 把
.sync
优化到了v-model
里面了。 - 把
$listeners
所有的东西,合并到$attrs
中了。
组件关系 | 传递方式 |
---|---|
父传子 | 1.props 2. v-model 3.$refs 4. 默认插槽、具名插槽 |
子传父 | 1.props 2. v-model 3.$parent 4. 自定义事件、作用域插槽 |
祖传孙、孙传祖 | 1.¥attrs 2. provide、inject |
兄弟间、任意组件间 | 1.mitt 2. pinia |
2、常用组件通信方式说明
2.1 【props】
- 概述:
props
是使用频率最高的一种通信方式,常用与 :父 ↔ 子。
- 若 父传子:属性值是非函数。
- 若 子传父:属性值是函数。
- 代码示例:
-
父组件
<template> <div class="father"> <h3>父组件</h3> <h4>父组件定义的变量:{{ car }}</h4> <h4 v-show="toy">来自子组件的返回值:{{ toy }}</h4> <Child :car="car" :sendToy="getToy"/> </div> </template> <script setup lang="ts" name="Father"> import Child from './Child.vue' import {ref} from 'vue' // 数据 let car = ref('父组件定义的变量:奔驰车') let toy = ref('') // 通过函数借子组件库调用 function getToy(value:string){ toy.value = value } </script>
-
子组件
<template> <div class="child"> <h3>子组件</h3> <h4>子组件自有变量:{{ toy }}</h4> <h4>来自父组件的props值:{{ car }}</h4> <button @click="sendToy(toy)">把玩具返回给父组件</button> </div> </template> <script setup lang="ts" name="Child"> import { ref } from 'vue'; // 声明接收props defineProps(['car', 'sendToy']); // 数据 let toy = ref('我最受的玩具是奥特曼'); </script>
2.2【自定义事件】
-
概述:自定义事件常用于:子 => 父。,一般和
props
配套使用,在组件通信中使用频率较高。 -
代码示例
<!--在父组件中,给子组件绑定自定义事件:--> <Child @send-toy="saveToy"/> // 父组件中的saveToy方法 function saveToy(value:string){ toy.value = value } <!--子组件,事件声明与触发--> //子组件中,声明事件: const emit = defineEmits(['send-toy']) // 事件触发 emit('send-toy',toy)
2.3 【v-model】
- 概述:实现 父↔子 之间相互通信。
- v-model的本质
组件标签上的v-model
的本质::moldeValue
+update:modelValue
事件的组合。<!-- 组件标签上使用v-model指令 --> <child v-model="userName"/> <!-- 组件标签上v-model等价于下面的示例 --> <child :modelValue="userName" @update:model-value="userName = $event"/>
- 代码示例
父组件<template> <div class="father"> <h3>父组件</h3> <!-- 修改modelValue --> <Child v-model:name="book" v-model:price="price" /> </div> </template> <script setup lang="ts" name="Father"> import { ref } from 'vue'; import Child from './child.vue'; // 数据 let book = ref('三国演示'); let price = ref(90); </script>
子组件代码
<template>
<div class="child">
<h3>子组件</h3>
<input type="text" :value="name" @input="changeName((<HTMLInputElement>$event.target).value)" />
<br />
<input type="text" v-model="childPrice" @input="changePrice(childPrice)" />
</div>
</template>
<script setup lang="ts" name="AtguiguInput">
// 接收props参数
const props = defineProps(['name', 'price']);
// 事件定义
const emit = defineEmits(['update:name', 'update:price']);
// 子组件变量声明
let childPrice = props.price;
function changeName(val: string) {
emit('update:name', val);
}
function changePrice(val: number) {
emit('update:price', val);
}
</script>
2.4 【$attrs 】
-
概述:
$attrs
用于实现当前组件的父组件,向当前组件的子组件通信(祖→孙)。 -
具体说明:
$attrs
是一个对象,包含所有父组件传入的标签属性。注意:
$attrs
会自动排除props
中声明的属性(可以认为声明过的props
被子组件自己“消费”了) -
代码示例
<!-- 子组件传值 -->
<Child :a="a" :b="b" :c="c" :d="d" v-bind="{x:100,y:200}" :updateA="updateA"/>
<!-- 子组件中通过$attrs传导 -->
<GrandChild v-bind="$attrs"/>
<!-- 孙组件中使用 -->
defineProps(['a','b','c','d','x','y','updateA'])
2.5 【$refs、$parent】
-
概述:
$refs
用于 :父→子。$parent
用于:子→父。
-
原理如下:
属性 说明 $refs
值为对象,包含所有被 ref
属性标识的DOM
元素或组件实例。$parent
值为对象,当前组件的父组件实例对象。 -
注意事项
通过$refs
和$parent
访问时,需要在相应组件中通过defineExpose
把要操作的变量或函数暴露出来,否则访问不到相关变量与函数。
2.6 【provide、inject】
-
概述:实现祖孙组件直接通信
-
具体使用:
- 在祖先组件中通过
provide
配置向后代组件提供数据 - 在后代组件中通过
inject
配置来声明接收数据
- 在祖先组件中通过
-
核心代码示例
// 向后代提供数据
provide('moneyContext',{money,updateMoney})
provide('car',car)
// 在需要使用的组件中进行接收
let {money,updateMoney} = inject('moneyContext',{money:0,updateMoney:(param:number)=>{}})
let car = inject('car',{brand:'未知',price:0})