1、props:常用与 ** 父 ↔ 子**。
- 若 父传子:属性值是非函数。
- 若 子传父:属性值是函数。
// 父组件
<template>
<child :car="car" :getToy="getToy" />
</template>
<script lang="ts" setup>
import child from "../detail/index.vue";
import { ref } from "vue";
const car = ref('宝马')
const toy = ref()
// 方法
function getToy(value:string){
console.log(value); //打印子组件传递过来的数据
toy.value = value
}
</script>
// 子组件
<template>
<h3>{{ car }}{{toy}}</h3>
<el-button @click="getToy(toy)">原生事件传给父组件</el-button>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { defineProps } from 'vue';
const toy = ref('奥特曼')
defineProps(['car','getToy'])
</script>
2、自定义事件
<!-- 父组件 -->
<child @send-toy="handler" />
const handler = (p1: any,p2: any) =>{
console.log(p1,p2,'自定义事件传值'); // 苹果 香蕉 自定义事件
}
<!-- 子组件 -->
<el-button @click="handlers">自定义事件send-toy</el-button>
import { defineEmits } from 'vue';
// 自定义事件传递数据
let $emit = defineEmits(['send-toy'])
const handlers =()=>{
$emit('send-toy','苹果','香蕉')
}
3、mitt :可以实现任意组件间通信
// 安装mitt 官网地址 https://www.npmjs.com/package/mitt
npm i mitt
新建文件:src\utils\emitter.ts
// 引入mitt
import mitt from "mitt";
// 创建emitter
const emitter = mitt()
// 暴露mitt
export default emitter
提供数据的组件,在合适的时候触发事件
<!-- 发送数据的组件 -->
<el-button @click="handler2">点击我给兄弟送点金币</el-button>
import emitter from "@/utils/emitter";
const handler2=()=>{
emitter.emit('maryy',{maryy:'1000$'})
}
接收数据的组件中:绑定事件、同时在销毁前解绑事件
import emitter from "@/utils/emitter";
import { onUnmounted } from "vue";
// 接收数据
emitter.on('maryy',(value)=>{
console.log(value); // {maryy: '1000$'}
})
onUnmounted(()=>{
// 销毁前解绑事件
emitter.off('maryy')
})
4、v-model:实现 父↔子 之间相互通信。
<!-- 父组件 -->
<!-- <child :modeValue="money" @update:modeValue="handler" /> -->
<!-- 上面这种方式也可以使用语法糖 v-model -->
<child v-model:money="money" v-model:car="car" />
import child from "../detail/index.vue";
const car = ref('宝马')
let money = ref(100)
const handler = (value: any) =>{
money.value = value
console.log(value,'modeValue');
}
<!-- 子组件 -->
<h3>{{money}},{{car}}</h3>
<el-button @click="handler">父子组件数据同步</el-button>
<!-- 触发自定义事件向父组件传递数据 -->
<el-button @click="$emit('update:car', `${car}太酷了`)">
car:{{ car }}
</el-button>
import { defineProps,defineEmits } from 'vue';
// 接收props数据
let props = defineProps(['money','car'])
let $emit = defineEmits(['update:money','update:car'])
// 子组件内部按钮的点击事件
const handler=()=>{
// 触发自定义事件向父组件传递数据
$emit('update:money',props.money+100)
}
5、$attrs : 用于实现当前组件的父组件,向当前组件的子组件通信(祖→孙)。
<!-- 父组件 -->
<card :a="a" v-bind="{x:100,y:200}" :updateA="updateA" />
import card from './components/card.vue'
let a = ref(1)
let b =ref(0)
function updateA(value: number){
b.value = value
console.log(b.value); //666
}
<!-- 子组件 -->
<child v-bind="$attrs" />
import child from "../detail/index.vue";
<!-- 孙组件 -->
<h3>{{a}},{{x}},{{y}}</h3>
<el-button @click="updateA(666)">点我更新a的值</el-button>
import { defineProps } from 'vue';
defineProps(['a','x','y','updateA'])
6、 【refs、$parent】
$refs
用于 :父→子。$parent
用于:子→父。
待总结…
7、provide、inject: 实现 ** 祖孙 ** 直接通信
【第一步】父组件中,使用provide
向后代组件提供数据
<!-- 父组件 -->
<card />
import card from './components/card.vue'
import {ref ,provide} from 'vue';
let car = ref('国产比亚迪')
let money =ref(1000)
// 用于更新money的方法
function updateMoney(value:number){
money.value += value
console.log(money.value); // 1600
}
// 提供数据
provide('moneyContext',{money,updateMoney})
provide('car',car)
子组件中不用编写任何东西,是不受到任何打扰的
【第二步】孙组件中使用inject
配置项接受数据。
<!-- 孙组件 -->
<h3>{{car}},{{money}}</h3>
<el-button @click="updateMoney(600)">点我更新</el-button>
import { inject } from 'vue'
// 接收数据
let {money,updateMoney} = inject('moneyContext',{money:0,updateMoney:(x:number)=>{}})
let car = inject('car')
8、pinia
请参考我的主页:vue pinia状态管理库的使用
9、slot
待总结…