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>
相关推荐
布列瑟农的星空几秒前
大话设计模式——关注点分离原则下的事件处理
前端·后端·架构
yvvvy19 分钟前
前端必懂的 Cache 缓存机制详解
前端
北海几经夏35 分钟前
React自定义Hook
前端·react.js
龙在天39 分钟前
从代码到屏幕,浏览器渲染网页做了什么❓
前端
TimelessHaze40 分钟前
【performance面试考点】让面试官眼前一亮的performance性能优化
前端·性能优化·trae
yes or ok1 小时前
前端工程师面试题-vue
前端·javascript·vue.js
我要成为前端高手1 小时前
给不支持摇树的三方库(phaser) tree-shake?
前端·javascript
Noxi_lumors1 小时前
VITE BALABALA require balabla not supported
前端·vite
周胜21 小时前
node-sass
前端
aloha_2 小时前
Windows 系统中,杀死占用某个端口(如 8080)的进程
前端