Vue3组件通信概览
组件通信分为树组件和跨组件通信
树组件就是有直接关联关系的组件,比如:父子组件、祖孙组件
跨组件没有关联关系的组件:在层级较深的组件调用顶级的组件,比如某个组件传值定义在App.vue里面的组件,比如全局弹窗组件
组件树通信有:
props/emit
父组件
<template>
<div class="home">
<user-card :user="user" @update-user="updateUser" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import userCard from '@/components/userCard.vue'
const user = ref({
username: '张三',
age: 18
})
const updateUser = (data) => {
user.value = {
...user.value,
...data
}
}
</script>
子组件
<template>
<div class="user-card">
<h2>用户信息</h2>
<p>姓名:{{ user.username }}</p>
<p>年龄:{{ user.age }}</p>
<div class="info">
<button @click="$emit('updateUser', { username: 'Alan', age: 23 })">修改用户信息</button>
</div>
</div>
</template>
<script setup>
defineProps({
user: {
type: Object,
default: () => {}
}
})
</script>
proive/inject和emit
父组件
<template>
<div class="home">
<user-card @updateUser="updateUser" />
</div>
</template>
<script setup>
import { ref, provide } from 'vue'
import userCard from '@/components/userCard.vue'
const user = ref({
username: '张三',
age: 18
})
const updateUser = (data) => {
user.value = {
...user.value,
...data
}
}
provide('user', user)
子组件
<template>
<div class="user-card">
<h2>用户信息</h2>
<p>姓名:{{ user.username }}</p>
<p>年龄:{{ user.age }}</p>
<div class="info">
<button @click="$emit('updateUser', { username: 'Alan', age: 23 })">修改用户信息</button>
</div>
</div>
</template>
<script setup>
import { inject } from 'vue'
const user = inject('user', { username: 'xxx', age: 12 })
</script>
proive/inject和mitt
安装import mitt from 'mitt'
utils/emitter.js
import mitt from 'mitt'
const emitter = mitt()
export default emitter
父组件
<template>
<div class="home">
<user-card />
</div>
</template>
<script setup>
import { ref, provide, onMounted, onUnmounted } from 'vue'
import userCard from '@/components/userCard.vue'
import emitter from '@/utils/mitter'
const user = ref({
username: '张三',
age: 18
})
onMounted(() => {
emitter.on('updateUser', (data) => {
user.value = {
...user.value,
...data
}
})
})
onUnmounted(() => {
emitter.off('updateUser')
})
provide('user', user)
</script>
子组件
<template>
<div class="user-card">
<h2>用户信息</h2>
<p>姓名:{{ user.username }}</p>
<p>年龄:{{ user.age }}</p>
<div class="info">
<button @click="updateUser">修改用户信息</button>
</div>
</div>
</template>
<script setup>
import { inject } from 'vue'
import emitter from '@/utils/mitter'
const user = inject('user', { username: 'xxx', age: 12 })
const updateUser = () => {
emitter.emit('updateUser', { username: 'Alan', age: 23 })
}
</script>
跨组件通信
使用mitt
使用mitt里面的on、emit、off等方法,组件树里面有介绍
使用pinia
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
A组件
<template>
<div class="home">
<h1>数值是:{{ useCounter.count }}</h1>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const useCounter = useCounterStore()
</script>
B组件
<template>
<div class="user-card">
<h2>数值变化</h2>
<div class="info">
<button @click="useCounter.increment()">+1</button>
</div>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const useCounter = useCounterStore()
</script>