父子组件通信
(1)props 父 -> 子
子组件通过 props 属性来接收父组件的数据,然后父组件在子组件上注册监听事件,子组件通过 emit 触发事件来向父组件发送数据。
- 父组件:使用子组件并添加属性,将 data 里的属性值绑定传入
- 子组件:通过 props 接收,在 methods 或生命周期里以
this.XXX的方式使用
// 父组件
<template>
<son :name="username" />
</template>
<script>
import son from './son.vue';
export default {
components: { son },
data() {
return {
username: 'lucy'
}
}
}
</script>
// 子组件
props: {
name: {
type: String,
default: ''
}
},
methods:{
f1(){
this.name='jack';
},
}
(2)this.$emit 子 -> 父
- 子组件:在methods的函数里
this.$emit(事件名,传参)向外弹出一个自定义事件。 - 父组件:使用子组件时监听该事件,获取参数:
@事件名=传参。
//子组件
<button @click="updateUser">点我</button>
...
props: ['user'],
events: ['update:user'],
methods: {
updateUser(){
this.$emit('update:user',this.user+'!')
}
}
//父组件
<son v-bind:user="username" @update:user="username=$event" />
上述写法等价于
<son v-model:user="username" />
注意:emit原则上可以弹出任何自定义事件,但使用v-model简写时,emit触发的必须是update:props属性这类事件。
(3)$attrs 父 -> 子(非 props 属性)
$attrs 可以获取父组件传进来,没有通过props接收的属性
// 父组件
<Child :title="title" :desc="desc" >/>
// 子组件内
<template>
<div>
<h2>{{title}}</h2>
<p>{{$attrs.desc}}</p>
</div>
</template>
<script>
export default {
props: ['title']
// ...
}
<script>
(4)插槽 子->父传值
希望在父组件内能够使用子组件内的变量 item ,将变量绑定到插槽上。
// 子组件
<ul>
<li v-for="(item,index) in news">
<slot :item="item" :index="index"></slot>
</li>
</ul>
...
data() {
return {
news: ['first news', 'second news']
}
}
父组件v-slot获取子组件插槽传过来的参数
// 父组件
<son v-slot="props">第{{props.index}}章{{props.item}}</slot>
爷孙 依赖/注入(provide/inject)
适用于深层嵌套的组件,一个顶层父组件可以为所有后代组件直接提供数据。
在父组件中通过 provide 提供变量,在子组件中通过 inject 来将变量注入到组件中。不论子组件有多深,只要调用了 inject 那么就可以注入 provide 中的数据。
// 顶层父组件
export default {
// ...
provide(){
return {
message: 'hello world!'
}
}
}
// 后代组件
export default {
// ...
inject: ['message'],
}
任意两个组件通信
(1)事件总线 EventBus
创建一个事件中心来管理组件之间的通信。
// event-bus.js
import Vue from 'vue';
export const eventbus = new Vue();
任意组件一:
// 触发事件
import { eventbus } from './event-bus.js'; // 引入事件中心
export default {
// methods 里
eventbus.$emit('termWord', itemData.orgChunk);
}
任意组件二:
import { eventbus } from './event-bus.js';
export default {
data() {
return {
termWord: '',
val: '',
}
}
// mounted 里监听事件
eventbus.$on('termWord', (val) => {
this.termWord = val;
});
// beforeDestroy 取消监听
eventbus.$off('termWord');
}
- 问题:如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,项目维护困难。
- 解决:使用 Vuex。将这些公共的数据抽离出来,作为一个全局的变量来管理,然后其他组件就可以对这个公共数据进行读写操作。
(2)Vuex 状态管理
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库,用于任意组件的任意通讯。
- store 创建的全局唯一的状态管理仓库,包含以下所有内容:
- State 用来读取状态,带有一个 mapState 辅助函数
- Getter 用来读取派生状态,附有一个 mapGetters 辅助函数
- Mutation 用于同步提交状态变更,附有一个 mapMutations 辅助函数(同步写)
- Action 用于异步变更状态,但它提交的是 mutation,而不是直接变更状态(一步写)
- Module 用来给 store 划分模块,方便维护代码。
//src/store/mutation-types.js
export const SET_GUIDE_SHOW = 'SET_GUIDE_SHOW';
// global.js
import * as types from '../mutation-types';
// 初始state状态
const stateGlobal = {
guideShow: 0,
}
// 可以做filter数据处理,也可以原始输出
const getters = {
getGuideShow: (state) => state.guideShow,
}
// 可以异步获取数据,也可以在组件中使用dispatch来发出actions
const actions = {
[types.SET_GUIDE_SHOW]({ commit }, guideShow) {
commit(types.SET_GUIDE_SHOW, guideShow);
},
}
// 更新state状态
const mutations = {
[types.SET_GUIDE_SHOW](state, guideShow) {
state.guideShow = guideShow;
},
}
使用
import { mapGetters } from 'vuex';
import { SET_GUIDE_SHOW } from '@/store/mutation-types';
export default {
...mapGetters([
'getGuideShow',
]),
// this.getGuideShow
详细可访问下方Vuex文档学习 vuex.vuejs.org/zh/