详解Vue之组件传值
Vue中的组件传值,也叫组件之间的通讯,主要分为下面三种:
- 父传子 :父组件向子组件传递数据
- 子传父 :子组件向父组件传递数据
- 非父子组件传值 :没有父子关系的组件之间传递数据。
下面分别详解。
一、父传子
父组件中传递:在子组件上绑定一个自定义属性,值为父组件向子组件传递的数据。
子组件中接收:在组件中通过属性props接收,props可以是一个对象,也可以是一个数组。
数组写法:
对象写法:
通讯结果:
二、子传父
父组件中接收:在子组件上绑定一个自定义事件,事件触发后的参数 value 就是子组件传递过来的数据。
子组件中传递:调用this.$emit ( 事件名称 , 向父组件传递的参数 )。这里的事件名称必须和子组件中自定义事件名称一致。
通讯结果:
三、非父子组件传值
1. 特殊的非父子组件传值( 爷孙组件传值 ) 只能从爷组件向下传递
爷组件向孙组件传递:provide —> 可以是一个函数也可以是一个对象。具体语法如下。
对象写法: 这种写法只能传递固定的数据,data中的响应式数据是取不到的。
函数写法: 这种写法能取到data中的响应式数据。
孙组件接收数据:inject —> 可以是一个数组也可以是一个对象。具体语法如下。属性名要和传递数据时定义的名称一致。
数组写法:
对象写法:
通信结果:
2. 普通非父子组件传值 ——也叫EventBus
给Vue原型上添加Vue实例,通过Vue实例上的$on 和 $emit 来进行事件的订阅和触发,事件名称必须一致。
传递数据: 触发事件
接收数据: 订阅事件
通讯结果:
3. 通用的组件传值方法 ——公共状态管理——Vuex,一种最好的非父子组件传值的一种方案
所谓的Vuex就是一个公共的内存对象,它把所有组件需要共有的状态放到了一个公共的内存空间里。并且给每一个状态做了一个数据劫持。
使用方法:
- 安装:
cnpm i Vuex -S
yarn add Vuex
- 引入插件:
import Vuex from “vuex”
import Vue from 'vue'
- 使用插件:
Vue.use(Vuex)
- 创建公共的内存对象:
const store =new Vuex.Store({ state: { }, mutations: { }, actions: { }, modules: { } })
- 将Vuex导出挂载到Vue身上: `new Vue({+
store,
render: h => h(App)
}).$mount(’#app’)`
Vuex 中 常用的配置项:
- state: 存储公共的状态,相当于Vue中的data。
state: { count:0 }
通过this.$store.state.key
来渲染在组件上。 - actions: 主要用来处理异步操作的
actions里的函数都有两个参数,第一个是对象,可以结构出来一个commit方法,第二个参数可以是传递的参数。其中commit方法中有两个参数,第一个参数是在mutations中注册的函数,第二个参数可以是传递的参数
actions: {
actiHandler({commit},params){ // 这里的第一个参数是一个对象,结构出一个commit函数。
commit("mutaHandler",params) //这里的commit函数的第一个参数是在mutations中注册的函数
//名称必须一致
}
}
- mutations: 修改公共状态
mutations里的函数都有两个参数,第一个是state,第二个是传递的参数。在这个阶段就可以对公共状态中的数据进行修改了。
mutations: {
mutaHandler(state,params){
state.count+=params.num // 第一个参数就是存储的公共状态,第二个参数可以是传递的参数
}
}
- module & setter : 持续更新中……
Vuex怎么修改数据( 修改数据的流程 )?
- 同步修改数据: 在要修改的组件中直接调用 commit 方法 触发mutations中对应的方法。
// 在组件中直接调用commit 方法 触发mutations中对应的方法。
methods:{
clickHandler(){
this.$store.commit('increment',5)
}
}
//在store中设置该方法。
mutations: {
increment(state,params){
state.count+=params
}
}
结果 :每次点击都会修改。
在Vue调试工具Vue-devtools 中能很好的检测函数的执行以及数据的变化(时间旅行)
2. 异步修改数据: 在要修改的组件中调用dispatch方法,该方法有两个参数,第一个是函数名,第二个可以是要传递的参数。函数名对应了在 actions 中注册的函数。然后actions注册的函数有两个参数,第一个是一个对象,解构出commit方法,第二个可以是要传递的参数,commit方法第一个参数是函数名,第二个可以是要传递的参数,函数名对应了在mutations中注册的函数。最后执行对数据的修改。
//在对应组件中调用 dispatch方法。
methods:{
clickHandler(){
this.$store.dispatch('ActiIncrement',5)
}
}
//在store中配置对应方法
const store =new Vuex.Store({
state: {
count:0
},
mutations: {
mutaIncrement(state,params){
state.count+=params
}
},
actions: {
ActiIncrement({commit},params){
setTimeout(()=>{
commit("mutaIncrement",params)
},3000)
}
}
})
结果: 三秒后执行。
调试工具中的时间旅行:
Vuex修改公共状态中的数据为什么要按照以上的流程呢?
在Vuex中,直接执行mutations中的方法修改数据,是可以实现的,但是在调试工具中没有变化,没有数据的时间旅行,如果是一个较大的Vue项目,这样修改数据,是非常不利于调试的。所以一定要按照流程走。