### 一. 父子组件之间通信:
1. defineProps 父组件通过 props 的方式向子组件传递数据 ,父组件通过:XXX="YYY"将值传递给子组件,子组件通过 defineProps 进行接收
父组件:
<div class="props">
<input v-model="message"/>
<child :message="message"></child>
</div>
const message = ref('我是父组件的内容')
子组件:
<div>
<p>我是子组件接受父组件的内容+{{ message }}</p>
</div>
defineProps({
message: {
type: String,
default: 'children',
},
})
2. 通过$emit 子组件可以向父组件通信。注意:props 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 props 只读。
2.1:v-model用于在父组件和子组件之间双向绑定数据。当父组件中的数据更新时,子组件的数据也会被更新,反之亦然。
父组件
<div class="emit">
<!-- 不需要绑定事件,当值更新时自动触发visible的更新 -->
<child v-if="visible" v-model:visible="visible"></child>
<button @click="visible = true">父组件打开弹窗</button>
</div>
子组件:
const emits = defineEmits(['update:visible'])
emits('update:visible',!props.visible )
2.2:子组件通过defineEmits触发了名为Result的自定义事件向父组件传递了为son的值
父组件:
const Result = (item) => {
result.value = item
}
子组件:
const son = ref('我是子组件的内容')
const hand = () => {
console.log(son.value,'1');
emits('Result',son.value)
}
3. 通过插槽实现父子组件件通信,让父组件可以向子组件指定位置插入 html 结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件。分类:默认插槽、具名插槽、作用域插槽
3.1 默认插槽:指在父组件中没有使用具名插槽来插入内容时,会被默认放置在子组件中的特殊插槽,子组件通过<slot></slot>进行接收
父组件:
<defalt aa="默认插槽">
<li v-for="item of arr">{{ item }}</li>
</defalt>
子组件:
<div>
<p>{{ aa }}</p>
<slot></slot>
</div>
3.2 具名插槽:用于插入具有特定名称的内容的一种方式,父组件在template标签中使用#xxx命名,子组件使用<slot name="xxx"></slot>进行接收,这样父组件的内容就会被展示在指定的位置
父组件:
<named bb="具名插槽">
<template #footer>
<div>这是尾部插槽</div>
</template>
</named>
子组件:
<div>
<p>{{ bb }}</p>
<slot name="footer"></slot>
</div>
3.3 作用域插槽:子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容
父组件:
子组件:
<div>
<p>{{ cc }}</p>
<slot :food="food"></slot>
</div>
4. provide/inject:为了解决祖孙之间传值,不论组件嵌套多深,父组件都可以为所有子组件或孙组件提供数据,父组件使用 provide 提供数据,子组件或孙组件inject 注入数据。
父组件:
const message = ref(123)
provide('CHILD',message)
子组件:
let result = inject('CHILD')
### 二. 非父子组件之间通信:
1.vuex状态管理工具
1.1 组件中通过 provide 来提供变量, 然后再子组件中通过 reject 来注入变量。主要解决了跨级组件间的通信问题,它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。不论子组件嵌套有多深, 只要调用了 inject 那么就可以注入 provide 中的数据,而不局限于只能从当前父组件的 props 属性中去取数据。
1.2 访问子组件实例或子元素\n\n 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;\n 如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据
1.3Vuex\n\nVuex 是一种状态管理模式。它采用集中式存储管理应用的所有组件的状态,state:用于数据的存储,是 store 中的唯一数据源。getters:如 vue 中的计算属性一样,基于 state 数据的二次包装,常用于数据的筛选和多个数据的相关性计算。mutations:类似函数,改变 state 数据的唯一途径,且不能用于处理异步事件。actions:类似于 mutation,用于提交 mutation 来改变状态,而不直接变更状态,可以包含任意异步操作。
组件:
<div>
<p>Count: {{ $store.state.count }}</p>
<p>double Count: {{ $store.getters.doubleCount }}</p>
<button @click="$store.commit('add')">加</button>
<button @click="$store.commit('lower')">减</button>
<button @click="$store.dispatch('async')">延迟</button>
</div>
仓库:
export default createStore({
state() {
return {
count: 0
}
},
mutations: {
add(state)
state.count++
},
lower(state) {
state.count--
}
},
actions: {
async({ commit }) {
setTimeout(() => {
commit('add')
}, 1000)
}
},
getters: {
doubleCount(state) {
return state.count * 2
}
}
})
2.消息订阅与发布:vue3中没有像vue2类似的全局事件总线,要想实现组件间通信可以引入第三方库mitt
2.1安装mitt
npm install mitt
2.2在main.js中引入注册
import mitt from 'mitt'
2.3实例化mitt
export const bus = mitt()
2.4在项目需要的地方导入mitt即可
import bus from './mitt'
2.5在代码中演示
父组件
bus.mitt('mittt',value)
子组件
emit.on('mittt',(value) => {
console.log(value)}
)
emit.on('mittt',,fun(value))
const fun = () => {
console.log(value)
}