最近遇到组件传值的问题特别多,索性自己总结下吧
一、单向传值
1. 父传子型
核心:利用props传递
父组件中 标签中定义动态属性
例如:
在父组件中
<template>
<div :son='father'></div>
</template>
<script>
export default {
data () {
return {
father: '张三'
}
}
}
</script>
在子组件中
<script>
export default {
props: ['son']
data () {
return {
name: ''
}
},
methods: {
this.name = this.son
console.log(this.name) // '张三' 子组件视图中 直接{{son}} 就可解析出值 张三
}
}
</script>
2.子传父
子组件通过$emit抛出自定义事件传递数据
例如:
子组件中:
<template>
<div @click="aaa"></div>
</template>
<script>
export default {
methods: {
aaa () {
// this.$emit('自定义事件名', 传过去参数数据) 子组件通过抛出事件
this.$emit('son', {a: 1, b: 2})
}
}
}
</script>
父组件中
<template>
<div @son="bbb"></div>
</template>
<script>
export default {
methods: {
bbb (obj) {
console.log(obj) // {a:1, b:2}
}
}
}
</script>
二、双向传值
1.任意组件通过事件总线
原理如图:
第一步:在main.js中 给Vue原型上补充$eventBus属性
Vue.prototype.$eventBus = new Vue()
第二步:任意组件发布事件
this.$ eventBus.$ emit(‘自定义事件名’,参数)
this.$eventBus.$emit('aaa',{a:1, b:2})
第三步: 任意组件监听 (谁监听谁能拿到传递过来的值)
this.$ eventBus.$ on(‘监听的事件名’,事件处理函数)
this.$eventBus.$on('aaa',(obj) => {
console.log(obj) // {a:1, b:2}
})
2.父子互传
原理:其实是 自定义属性value 和 自定义事件input 的快捷使用。
格式:
// 父组件
data: { return { channel_id: ‘’}}
// 1. 使用。 在子组件使用v-model。与在普通表单元素上使用是一样的。
<my-channels v-model="channel_id"></my-channels>
// 2. 在子组件my-channels的内部:
// (1) 设置一个名为value的属性来获取从父组件传的v-model的初值
// (2) 在某个时间点,触发名为input的事件,来修改父组件中v-model的值
具体如图案例
3.vuex也可以实现组件之间传值
vuex的作用是解决多组件状态共享的问题。
它是独立于组件而单独存在的,所有的组件都可以把它当作一座桥梁来进行通讯。
与事件总线相比,它具备额外的特点:
响应式
操作更简洁
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
// 各种配置项
// state 就相当于vue组件中的data。它用来存放整个vue项目中公共的数据
// 这个数据,在所有的vue组件中都可以访问到
state: {
num: 101,
count: 21.5,
person: {
name: '张三'
}
},
mutations: {
// 下面定义了一个mutation。本质就是一个函数
// 特殊之处:在定义函数时,第一个参数就表示当前vuex中的state
// 直接在此函数内部去修改state.
// 在调用这个函数时,第一个参数不要传入。
// 1.不带参数的mutation
mAdd1(state){
// 这个mutation的作用就是让state中的num加1
state.num++
},
// 2. 带参数的mutation
mAddN(state, n){
// 这个mutation的作用就是让state中的num加 n
// 这个n是需要额外传入的
state.num = state.num + n
}
}
});
其他组件要获取或者设置公共资源数据
第一种直接获取
<button @click="Add">+1</button>
methods:{
methods: {
add () {
// 直接修改state,不推荐
// this.$store.state.num++
// 调用了Vuex.store配置项中的mutations对象中的名为mAdd1的方法。
// 不需要传入任何参数。
this.$store.commit("mAdd1")
},
addN () {
// 调用一个带参数的mutation
this.$store.commit('mAddN', 10)
}
}
}
第二种 通过映射
<script>
// 在组件中通过映射的方式来使用vuex中的mutations
// 1. 引入工具函数
import { mapMutations } from 'vuex'
// mapMutations 是一个函数,在vue中定义的。
// mapMutations(['mAdd1', 'mAddN'])的返回值是一个对象
// 这个对象类似于{mAdd1:function(){}, mAddN:function(){}}
// 2. 在methods中 插入 映射函数的结果
export default {
name: 'SubItem',
// 下面的代码中,相当于methods中定义了 4个方法
// sub,mAdd1,mAddN, test
methods: {
sub () {
this.$store.state.num--
},
...mapMutations(['mAdd1', 'mAddN']),
test () {
// 由于上面的mAdd1并映射成方法,所以这里可以直接加this.来访问。
// this.mAdd1()
this.mAddN(100)
}
}
}
</script>