vue3的组件通信方式

1、props传递(父子互传)

父组件部分(props实现父传子,props传):

js 复制代码
<template>
  <div class="father">
    <h1>Father - Father - Father - 父传子</h1>
    <div class="f"> {{ `父亲有的:房子:${hourse}套, 资产:${money}` }}</div>
    <hr>
    <div class="s">{{ `儿子给父亲的:车子:${sonAll.car || '--'}辆, 资产:${sonAll.money || '--'}` }}</div>
  </div>
  <Son :fatherAll="fatherAll" :sendFather="getFather"></Son>
</template>

<script setup lang='ts' name="father">
import { reactive, ref, toRefs } from 'vue';
import Son from "./Son.vue";
const fatherAll = reactive({
  hourse: 1,
  money: '100w'
})
let { hourse, money } = toRefs(fatherAll)

let sonAll = ref({})
function getFather(val: object) {
  Object.assign(sonAll.value, val)
}
</script>

<style scoped>
.father {
  width: 100%;
  height: 30vh;
  background-color: antiquewhite;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

子组件部分(defineProps实现子传父,defineProps传):

js 复制代码
<template>
  <div class="son">
    <h1>Son - Son - Son - 子传父</h1>
    <div class="s">{{ `儿子有的:车子:${car}辆, 资产:${money}` }}</div>
    <hr>
    <div class="f">{{ `父亲给儿子的:房子:${fatherAll.hourse}套, 资产:${fatherAll.money}` }}</div>
    <button @click="sendFather(sonAll)">儿子给父亲</button>
  </div>
</template>

<script setup lang='ts' name="son">
import { reactive, toRefs } from 'vue';
defineProps(['fatherAll', 'sendFather'])
const sonAll = reactive({
  car: '2',
  money: '100元'
})
let { car, money } = toRefs(sonAll)

</script>

<style scoped>
.son {
  width: 100%;
  height: 100%;
  background-color: azure;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

2、emit传递(子传父)

父组件部分(props实现父传子,props传):跟1里面的props传一摸一样

js 复制代码
<template>
  <div class="father">
    <h1>Father - Father - Father - 父传子</h1>
    <div class="f"> {{ `父亲有的:房子:${hourse}套, 资产:${money}` }}</div>
    <hr>
    <div class="s">{{ `儿子给父亲的:车子:${sonAll.car || '--'}辆, 资产:${sonAll.money || '--'}` }}</div>
  </div>
  <Son :fatherAll="fatherAll" @sendFather="getFather"></Son>
</template>

<script setup lang='ts' name="father">
import { reactive, ref, toRefs } from 'vue';
import Son from "./Son.vue";
const fatherAll = reactive({
  hourse: 1,
  money: '100w'
})
let { hourse, money } = toRefs(fatherAll)

let sonAll = ref({})
function getFather(val: object) {
  // console.log(123);
  Object.assign(sonAll.value, val)
}
</script>

<style scoped>
.father {
  width: 100%;
  height: 30vh;
  background-color: antiquewhite;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

子组件部分(defineEmits实现父传子,defineEmits传):

js 复制代码
<template>
  <div class="son">
    <h1>Son - Son - Son - 子传父</h1>
    <div class="s">{{ `儿子有的:车子:${car}辆, 资产:${money}` }}</div>
    <hr>
    <div class="f">{{ `父亲给儿子的:房子:${fatherAll.hourse}套, 资产:${fatherAll.money}` }}</div>
    <button @click="emit('sendFather', sonAll)">儿子给父亲</button>
  </div>
</template>

<script setup lang='ts' name="son">
import { reactive, toRefs } from 'vue';
defineProps(['fatherAll'])
const emit = defineEmits(['sendFather'])
const sonAll = reactive({
  car: '2',
  money: '100元'
})
let { car, money } = toRefs(sonAll)

</script>

<style scoped>
.son {
  width: 100%;
  height: 100%;
  background-color: azure;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

3、mitt传递(任意组件传递)

emmitter.ts文件

js 复制代码
// emmitter.ts文件
import mitt from 'mitt'
const emmitter = mitt()
export default emmitter

父组件部分(配合emmitter.ts, 父组件:emmitter.emit('sendSon', fatherAll)~~~配置50%):

js 复制代码
<template>
  <div class="father">
    <h1>Father - Father - Father - 父传子</h1>
    <div class="f"> {{ `父亲有的:房子:${hourse}套, 资产:${money}` }}</div>
    <hr>
    <div class="s">{{ `儿子给父亲的:车子:${sonAll?.car || '--'}辆, 资产:${sonAll?.money || '--'}` }}</div>
  </div>
  <Son></Son>
</template>

<script setup lang='ts' name="father">
import { onMounted, reactive, ref, toRefs } from 'vue';
import Son from "./Son.vue";
import emmitter from '../utils/emitter.ts';
const fatherAll = reactive({
  hourse: 1,
  money: '100w'
})
let { hourse, money } = toRefs(fatherAll)
let sonAll = ref({})
function sendSon() {
  // 父传子
  emmitter.emit('sendSon', fatherAll)
}
onMounted(() => {
  sendSon()
})

// 子传父
emmitter.on('sendFather', (val: any) => {
  Object.assign(sonAll.value, val)
})


</script>

<style scoped>
.father {
  width: 100%;
  height: 30vh;
  background-color: antiquewhite;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

子组件部分( 子组件emitter.on('sendSon', (val: any) => { Object.assign(fatherAll, val) })~~~配置100%,实现父子通信 )

js 复制代码
<template>
  <div class="son">
    <h1>Son - Son - Son - 子传父</h1>
    <div class="s">{{ `儿子有的:车子:${car}辆, 资产:${money}` }}</div>
    <hr>
    <div class="f">{{ `父亲给儿子的:房子:${fatherAll?.hourse || '--'}套, 资产:${fatherAll?.money || '--'}` }}</div>
  </div>
</template>

<script setup lang='ts' name="son">
import { reactive, toRefs, onMounted } from 'vue';
import emitter from '../utils/emitter.ts'
const sonAll = reactive({
  car: '2',
  money: '100元'
})
let { car, money } = toRefs(sonAll)
let fatherAll = reactive({})
// 父传子
emitter.on('sendSon', (val: any) => {
  Object.assign(fatherAll, val)
})

// 子传父
function sendFather() {
  emitter.emit('sendFather', sonAll)
}
onMounted(() => {
  sendFather()
})
</script>

<style scoped>
.son {
  width: 100%;
  height: 100%;
  background-color: azure;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

4、v-model传递(父子组件的input框-父子互传)

父组件部分(父组件:v-model:hourse~~~配置50%):

js 复制代码
<template>
  <div class="father">
    <h1>Father - Father - Father - 父传子</h1>
    <input class="f" :placeholder="`父亲有的:房子:${hourse}套, 资产:${money}`"> </input>
    <hr>
    <input class="s" :placeholder="`儿子给父亲的:车子:${sonAll?.car || '--'}辆, 资产:${sonAll?.money || '--'}`"> </input>
  </div>
  <input type="text" v-model="fatherAll.hourse">

  <Son v-model:hourse="fatherAll.hourse"></Son>
  <!-- 实际代码 -->
  <!-- <Son :hourse="fatherAll.hourse" @update:hourse="(val: any) => fatherAll.hourse = val"></Son> -->
</template>

<script setup lang='ts' name="father">
import { onMounted, reactive, ref, toRefs } from 'vue';
import Son from "./Son.vue";
const fatherAll = reactive({
  hourse: 1,
  money: '100w'
})
let { hourse, money } = toRefs(fatherAll)
let sonAll = ref({})


</script>

<style scoped>
.father {
  width: 100%;
  height: 30vh;
  background-color: antiquewhite;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
  height: 40px;
  width: 300px;
}

.s {
  color: red;
  height: 40px;
  width: 300px;
}
</style>

子组件部分(子组件::value="hourse" @input="emit('update:hourse', $event.target.value)"~~~配置100%):

js 复制代码
<template>
  <div class="son">
    <h1>Son - Son - Son - 子传父</h1>
    <input class="s" :placeholder="`儿子有的:车子:${car}辆, 资产:${money}`"> </input>
    <hr>
    <input class="f" :placeholder="`父亲给儿子的:房子:${fatherAll?.hourse || '--'}套, 资产:${fatherAll?.money || '--'}`"> </input>
    <hr>
    <hr>
    <input type="text" :value="props.hourse" @input="emit('update:hourse', $event.target.value)">
  </div>
</template>

<script setup lang='ts' name="son">
import { reactive, toRefs, onMounted } from 'vue';
let props = defineProps(['hourse'])
const emit = defineEmits(['update:hourse'])
const sonAll = reactive({
  car: '2',
  money: '100元'
})
let { car, money } = toRefs(sonAll)
let fatherAll = reactive({})

</script>

<style scoped>
.son {
  width: 100%;
  height: 100%;
  background-color: azure;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
  height: 40px;
  width: 300px;
}

.s {
  color: red;
  height: 40px;
  width: 300px;
}
</style>

4、$attrs传递(祖孙互传)

父组件(传数据fatherAll和方法sendFather给子组件~~~配置30%):

js 复制代码
<template>
  <div class="father">
    <h1>Father - Father - Father - 父传子</h1>
    <div class="f"> {{ `父亲有的:房子:${hourse}套, 资产:${money}` }}</div>
    <hr>
    <div class="s">{{ `儿子给父亲的:车子:${sonAll.car || '--'}辆, 资产:${sonAll.money || '--'}` }}</div>
  </div>
  <Son :fatherAll="fatherAll" :sendFather="getFather" v-bind="{ bed: 1, light: 10 }"></Son>
</template>

<script setup lang='ts' name="father">
import { reactive, ref, toRefs } from 'vue';
import Son from "./Son.vue";
const fatherAll = reactive({
  hourse: 1,
  money: '100w'
})
let { hourse, money } = toRefs(fatherAll)

let sonAll = ref({})
function getFather(val: number) {
  hourse.value = hourse.value + val
}
</script>

<style scoped>
.father {
  width: 100%;
  height: 30vh;
  background-color: antiquewhite;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

子组件(v-bind="$attrs"放在孙组件上~~~配置60%):

js 复制代码
<template>
  <div class="son">
    <h1>Son - Son - Son - 子传父</h1>
    父给子的其他数据:{{ $attrs }}
    <Grandson‌ v-bind="$attrs"></Grandson‌>
  </div>
</template>

<script setup lang='ts' name="son">
import Grandson‌ from './Grandson‌.vue'
</script>

<style scoped>
.son {
  width: 100%;
  height: 100%;
  background-color: azure;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

孙组件(defineProps()获取数据和方法~~~配置100%):

js 复制代码
<template>
  <div class="grandSon">
    <h1>grandSon - grandSon - grandSon - 祖传孙</h1>
    <div class="s">{{ `父亲给孙子的:房子:${fatherAll.hourse || '--'}套, 资产:${fatherAll.money || '--'}, 其他:床:${bed || '--'}个,
      灯:${light || '--'}个` }}</div>
    <button @click="sendFather(100)">孙传父</button>
  </div>
</template>

<script setup lang='ts' name="grandSon">
import { reactive, ref, toRefs } from 'vue';
defineProps(['fatherAll', 'bed', 'light', 'sendFather'])
</script>

<style scoped>
.grandSon {
  width: 100%;
  height: 30vh;
  background-color: aquamarine;
  border: 1px solid red;
  font-size: 28px;
}
</style>

5、$refs(父传子)

父组件(在引入的子组件中ref="sonRef",按钮配置@click="getSon($refs)"~~~配置50%):

xml 复制代码
<template>
  <div class="father">
    <h1>Father - Father - Father - 父传子</h1>
    <div class="f"> {{ `父亲有的:房子:${hourse || '--'}套, 资产:${money || '--'}` }}</div>
    <hr>
    <div class="s">{{ `儿子给父亲的:车子:${sonAll.car || '--'}辆, 资产:${sonAll.money || '--'}` }}</div>
    <button @click="getSon($refs)">获取儿子的数据</button>
    <Son ref="sonRef"></Son>
  </div>
</template>

<script setup lang='ts' name="father">
import { reactive, ref, toRefs, onMounted } from 'vue';
import Son from "./Son.vue";
const fatherAll = reactive({
  hourse: 1,
  money: '100w'
})
let { hourse, money } = toRefs(fatherAll)
let sonAll = ref({})
let sonRef = ref({})
function getSon(refs: { [key: string]: any }) {
  // 父传子
  refs['sonRef'].sonAll.money++
  Object.assign(sonAll.value, refs['sonRef'].sonAll)

}
</script>

<style scoped>
.father {
  width: 100%;
  height: 30vh;
  background-color: antiquewhite;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

子组件(提供父亲的数据sonAll:defineExpose({ sonAll })~~~配置100%):

xml 复制代码
<template>
  <div class="son">
    <h1>Son - Son - Son - 子传父</h1>
    <div class="s">{{ `儿子有的:车子:${car || '--'}辆, 资产:${money || '--'}` }}</div>
    <hr>
  </div>
</template>

<script setup lang='ts' name="son">
import { reactive, toRefs } from 'vue';
const sonAll = reactive({
  car: '2',
  money: 100
})
let { car, money } = toRefs(sonAll)

defineExpose({ sonAll })
</script>

<style scoped>
.son {
  width: 100%;
  height: 100%;
  background-color: azure;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

5、$parent(子传父)

父组件(提供儿子的数据money:defineExpose({ money })~~~配置50%):

js 复制代码
<template>
  <div class="father">
    <h1>Father - Father - Father - 父传子</h1>
    <div class="f"> {{ `父亲有的:房子:${hourse || '--'}套, 资产:${money || '--'}` }}</div>
    <hr>
    <div class="s">{{ `儿子给父亲的:车子:${sonAll.car || '--'}辆, 资产:${sonAll.money || '--'}` }}</div>
    <button @click="getSon($refs)">获取儿子的数据</button>
    <Son ref="sonRef"></Son>
  </div>
</template>

<script setup lang='ts' name="father">
import { reactive, ref, toRefs, onMounted } from 'vue';
import Son from "./Son.vue";
const fatherAll = reactive({
  hourse: 1,
  money: 10000
})
let { hourse, money } = toRefs(fatherAll)
let sonAll = ref({})
let sonRef = ref({})
function getSon(refs: { [key: string]: any }) {
  // 父传子
  refs['sonRef'].sonAll.money++
  Object.assign(sonAll.value, refs['sonRef'].sonAll)

}
//向儿子提供数据
defineExpose({ money })
</script>

<style scoped>
.father {
  width: 100%;
  height: 30vh;
  background-color: antiquewhite;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

子组件(按钮配置@click="changeMoney($parent)"~~~配置50%):

js 复制代码
<template>
  <div class="son">
    <h1>Son - Son - Son - 子传父</h1>
    <div class="s">{{ `儿子有的:车子:${car || '--'}辆, 资产:${money || '--'}` }}</div>
    <hr>
    <button @click="changeMoney($parent)">改变父亲的值</button>
  </div>
</template>

<script setup lang='ts' name="son">
import { reactive, toRefs } from 'vue';
const sonAll = reactive({
  car: '2',
  money: 100
})
let { car, money } = toRefs(sonAll)
function changeMoney(parent: any) {
  parent.money = parent.money - 10
}
defineExpose({ sonAll })
</script>

<style scoped>
.son {
  width: 100%;
  height: 100%;
  background-color: azure;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

6、provide、inject(祖孙互传)

组父组件(引入后直接用provide('fatherAll', fatherAll)~~~配置50%):

js 复制代码
<template>
  <div class="father">
    <h1>Father - Father - Father - 父传子</h1>
    <div class="f"> {{ `父亲有的:房子:${hourse}套, 资产:${money}` }}</div>
    <hr>
  </div>
  <Son></Son>
</template>

<script setup lang='ts' name="father">
import { reactive, ref, toRefs, provide } from 'vue';
import Son from "./Son.vue";
const fatherAll = reactive({
  hourse: 1,
  money: 100000
})
let { hourse, money } = toRefs(fatherAll)
// 组传孙
// provide('fatherAll', fatherAll)
provide('fatherAllContext', { f: fatherAll, updateMoney })

// 孙传组
function updateMoney(val: number) {
  money.value -= val
}
</script>

<style scoped>
.father {
  width: 100%;
  height: 30vh;
  background-color: antiquewhite;
  border: 1px solid red;
  font-size: 28px;
}

.f {
  color: green;
}

.s {
  color: red;
}
</style>

孙子组件(引入后直接用inject('fatherAll'}~~~配置100%):

js 复制代码
<template>
  <div class="grandSon">
    <h1>grandSon - grandSon - grandSon - 祖传孙</h1>
    <div class="s">{{ `父亲给孙子的:房子:${f.hourse || '--'}套,资产:${f.money}` }}</div>
    <button @click="updateMoney(10)">修改组的money</button>
  </div>
</template>

<script setup lang='ts' name="grandSon">
import { inject } from 'vue';
// 组传孙
// let f = inject('fatherAll', {
//   hourse: '默认值:1000',
//   money: '默认值:1000000'
// })
let { f, updateMoney } = inject('fatherAllContext', { f: {}, updateMoney: (params: number) => { } })

</script>
<style scoped>
.grandSon {
  width: 100%;
  height: 30vh;
  background-color: aquamarine;
  border: 1px solid red;
  font-size: 28px;
}
</style>
相关推荐
报错小能手1 分钟前
linux学习笔记(18)进程间通讯——共享内存
linux·服务器·前端
魔云连洲8 分钟前
深入解析:Object.prototype.toString.call() 的工作原理与实战应用
前端·javascript·原型模式
JinSo17 分钟前
alien-signals 系列 —— 认识下一代响应式框架
前端·javascript·github
开心不就得了23 分钟前
Glup 和 Vite
前端·javascript
szial25 分钟前
React 快速入门:菜谱应用实战教程
前端·react.js·前端框架
西洼工作室31 分钟前
Vue CLI为何不显示webpack配置
前端·vue.js·webpack
黄智勇1 小时前
xlsx-handlebars 一个用于处理 XLSX 文件 Handlebars 模板的 Rust 库,支持多平台使
前端
brzhang2 小时前
为什么 OpenAI 不让 LLM 生成 UI?深度解析 OpenAI Apps SDK 背后的新一代交互范式
前端·后端·架构
brzhang3 小时前
OpenAI Apps SDK ,一个好的 App,不是让用户知道它该怎么用,而是让用户自然地知道自己在做什么。
前端·后端·架构
井柏然4 小时前
前端工程化—实战npm包深入理解 external 及实例唯一性
前端·javascript·前端工程化