Vue组件间的数据通信
props配置项
-
功能:让组件接受外部传来的数据
- 传递数据:
<Demo name="xxx"></Demo>
- 接受数据:
- 只接受
props: ["name"],
- 限制类型接受
props: {
name: String,
}, - 限制类型,必要性限制,指定默认值接受
props: {
name: {
type: String,
required: true,
default: "胡先森"
},
},
- 只接受
- 传递数据:
-
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确定需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据
组件的自定义事件
-
一种组件间通信的方式,适用于:子组件===>父组件
-
使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)
-
绑定自定义事件
-
在父组件中
<Student @myClick="test"></Student>或者<Student v-on:myClick="test"></Student>
-
在父组件中
<Student ref="student"></Student>
...
mounted() {
this.$refs.student.$on("myClick", this.test);
} -
若想让自定义事件只能触发一次,可以使用once修饰符,或者$once方法
-
-
触发自定义事件:this.$emit("myClick", params)
-
解绑自定义事件:this.$off("myClick")
-
组件上也可以绑定原生DOM事件,需要使用native修饰符,特别是在使用了element-ui组件时,定义的事件一般都是用native修饰。
-
注意:通过this.$refs.student.$on("myClick", this.test)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
全局事件总线(GlobalEventBus)
-
一种组件间通信的方式,适用于任意组件间的通信
-
安装全局事件总线(main.js):
new Vue({
...
beforeCreate() {
// 安装全局事件总线,$bus就是当前应用的VM
Vue.prototype.$bus = this;
},
...
}) -
使用全局事件总线:
- 接受数据:A组件想接受数据,则在A组件中给$bus绑定自定义事件,事件的回调函数留在A组件中
methods: {
demo(data) {...},
},
mounted() {
this.$bus.$on("xxx", this.demo)
} - 提供数据
this.$bus.$emit("xxx", params)
- 接受数据:A组件想接受数据,则在A组件中给$bus绑定自定义事件,事件的回调函数留在A组件中
-
最好在beforeDestroy钩子中用$off去解绑当前组件所用到的事件
消息订阅与发布(pubsub)
-
一种组件间通信的方式,适用于任意组件间的通信。
-
使用步骤:
- 安装pubsub
npm install --save pubsub-js
- 引入
import pubsub from "pubsub-js"
- 接受数据:A组件想接受数据,则在A组件中订阅消息,订阅的回调函数留在A组件中
methods: {
demo(data) {...},
},
mounted() {
this.pubId = pubsub.subscribe("xxx", this.demo);
} - 提供数据
pubsub.publish("xxx", params);
- 安装pubsub
-
最好在beforeDestroy钩子中用
pubsub.unsubscribe(this.pubId);
去解绑当前组件所用到的事件
插槽
- 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于父组件===>子组件
- 分类:默认插槽、具名插槽、作用域插槽
-使用方式:
- 默认插槽:
- 父组件:
<Category>
<div>html结构</div>
</Category> - 子组件:
<template>
<div>
<!-- 定义插槽 -->
<slot>一些描述内容</slot>
</div>
</template>
- 父组件:
- 具名插槽:
- 父组件:
<Category>
<template slot="center">
<div>html结构</div>
</template>
<template slot="footer">
<div>html结构</div>
</template>
</Category> - 子组件:
<template>
<div>
<!-- 定义插槽 -->
<slot name="center">一些描述内容</slot>
<slot name="footer">一些描述内容</slot>
</div>
</template>
- 父组件:
- 作用域插槽:
-
理解:数据在组件自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
-
具体实现:
- 父组件:
<Category>
<template scope="dataset">
<ul>
<li v-for="(game, index) in dataset.games" :key="index">{{game}}</li>
</ul>
</template>
<template scope="dataset">
<ol>
<li v-for="(game, index) in dataset.games" :key="index">{{game}}</li>
</ol>
</template>
</Category> - 子组件:
<template>
<div>
<!-- 定义插槽 -->
<slot :games="games">一些描述内容</slot>
</div>
</template>
<script>
export default {
name: "Category",
props: ["title"],
data() {
return {
games: ['红色警戒', '穿越火线', '劲舞团', '超级玛丽'],
}
},
}
</script>
- 父组件:
-
- 默认插槽:
Vuex(可参考博主的Vuex的使用及map方法)
-
概念:在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间的通信
-
使用场景:多个组件需要共享数据
-
搭建Vuex环境
- 创建文件:src/store/index.js
// 该文件用于创建Vuex中最为核心的store
// 引入Vuex
import Vue from 'vue'
// 引入Vuex插件
import Vuex from "vuex"
Vue.use(Vuex)
// 准备actions--用于响应组件的动作
const actions = {}
// 准备mutations--用于操作数据(state)
const mutations = {}
// 准备state--用于存储数据
const state = {}
const store = new Vuex.Store({
actions,
mutations,
state,
})
export default store; - 在main.js中创建vm时传入store配置项
// 引入创建的store
import store from "./store"
new Vue({
el: '#app',
render: h=>h(App),
// 使用store
store,
...
})
- 创建文件:src/store/index.js
-
具体使用
- 组件使用
methods: {
add() {
this.$store.dispatch("add", params);
},
...
} - src/store/index.js配置
// 准备actions--用于响应组件的动作
const actions = {
add(context, value) {
context.commiit("ADD", value);
},
...
}
// 准备mutations--用于操作数据(state)
const mutations = {
ADD(state, value) {
state.sum += value;
},
...
}
// 准备state--用于存储数据
const state = {
sum: 0,
...
}
- 组件使用