Vue – 组件间的数据共享
简介
Vue 中一项重点知识是组件间的数据传递,在组件和组件之间形成的页面中,少不了组件与组件之间的数据传递,其中 Vue 有多种数据传递方式。
不管是组件间层级有多少,我们都可以统称为两种组件传递方式:
父子,子父间传递
兄弟间传递
父 -> 子 传递
比较简单和常见的传递方式,父传子通常使用 自定义属性 传递,子组件使用 props 接收。
注意:props 传递过来的是 父组件 传递的 属性 数据,其内存地址是一样的,Vue 不建议子组件直接修改 props 属性,但Vue只作为浅检查,若 props 属性为对象类型,则 子组件 中直接修改 props 属性对象中的成员,Vue 不会提示错误,因为修改对象中的成员,并不影响对象的内存地址,但依然不建议通过这种方式修改 props 属性。
子 -> 父 传递
子组件向父组件传递数据通常使用 自定义事件。
1.父组件中设置 v-on 设置自定义涵数。
<Father @change="SonChange"></Father>
2.父组件中建立 v-on 的自定义涵数实现,并声明形参接收来自子组件传递的数据
methods:{
SonChange(foo){
...
}
}
3.子组件中调用 this.$emit() 方法执行父组件涵数并传递数据到父组件中。foo则是来自子组件传递过来的数据
methods:{
SonButton(){
this.$emit('change',foo)
}
}
v-model
v-model 也可以实现父子之间的数据传递,主要以子->父为主,其原理是内置了自定义事件进行数据传递,因此在子组件中,需要调用$emit。
实现原理(v-model的实现原理):
1.父组件通过 props 单向的把数据传给子组件,此时数据的传递是单向的,props 只支持父->子
<template>
<div>
<!-- 父组件中的输入框 -->
<input type="text" v-model="message">
<!-- 给子组件 props 单向传递数据,再给子组件声明自定义事件 -->
<Child :msg="message" @change="message = $event" ></Child>
</div>
</template>
2.父组件对子组件设定一个自定义事件,并实现自定义事件的处理函数。
3.子组件中接收这个自定义事件,当子组件中的数据被改变后,可以通过$emit调用自定义事件把修改的数据回调到父组件,实现子传父
<template>
<div>
我是子组件
<!-- 在子组件中的文本框中,声明@input原生事件,当文本框数据被改变后,会调用 $emit 方法 -->
<input type="text" :value="msg" @input="$emit('change', $event.target.value)"/>
</div>
</template>
v-model 的实际使用:
通过上面的原理可知,v-model 是通过 props 与 自定义事件配合一起做数据传递的,那么在父组件中,就可以在子组件里直接使用 v-model 实现以上原理的数据传递。
父组件调用子组件使用 v-model
<Child v-model:msg="message" ></Child>
子组件接收并调用自定义事件,使用 update:xxx
<input type="text" :value="msg" @input="$emit('update:msg', $event.target.value)"/>
.sync 修饰符(Vue2)
sync 的使用和 v-model 的使用差不多,只是在父组件中定义传递数据时,使用 sync 修饰符即可。
<Child :msg.sync="message" ></Child>
子组件接收并调用自定义事件,使用 update:xxx
<input type="text" :value="msg" @input="$emit('update:msg',$event.target.value)"/>
注意:.sync 方式在 Vue3 中已与 v-model 合并,在Vue3 中使用 v-model 即何
$children 与 $parent 参数(Vue2)
Vue中提供了$children 与 $parent 参数,父组件中会在 $children 中保存了其下面引用的子组件的VC对象。而子组件中的 $parent 参数中也保存了调用了它的父组件VC对象,可以通过其两者的关系,向子组件或父组件传递数据。
注意:Vue3 中已不能使用。
兄弟间传递
在 Vue2.x 中,兄弟组件之间数据共享的方案是 EventBus.
EventBus [2.0]
EventBus 的使用步骤
① 创建eventBus.js 模块,并向外共享一个 Vue 的实例对象,用于数据存放和传递
import Vue from 'vue'
// 向外共享 Vue 的实例对象
export default new Vue()
② 在数据发送方,调用bus.$emit('事件名称', 要发送的数据) 方法触发自定义事件
import bus from './eventBus.js’
export default {
data() {
return {
msg: 'hello vue.js'
}
},
methods: {
sendMsg() {
bus.$emit('share', this.msg)
}
}
}
③ 在数据接收方的created方法里,调用bus.$on('事件名称', 事件处理函数) 方法注册一个自定义事件
import bus from './eventBus.js'
export default {
data() {
return { msgFromLeft: ''
}
},
created() {
bus.$on('share', val => {
this.msgFromLeft = val
})
}
}
EventBus [3.0]
兄弟组件之间实现数据共享的方案是EventBus。可以借助于第三方的包 mitt 来创建eventBus 对象,从而实 现兄弟组件之间的数据共享。
安装 miit 依赖
1.在项目中运行如下的命令,安装mitt 依赖包
2.在项目中创建公共的eventBus 模块
3.在数据接收方,调用bus.on('事件名称', 事件处理函数) 方法注册一个自定义事件。
4.在数据发送方,调用bus.emit('事件名称', 要发送的数据) 方法触发自定义事件。
向后代的数据共享[3.0]
父节点的组件可以通过provide 方法,对其子孙组件共享数据
子孙节点可以使用 inject 数组,接收父级节点向下共享的数据。
但是,使用这种方法,做不到响应式,即父组件数据改变了,子组件数据不会改变。
使数据变成响应式
父节点使用provide 向下共享数据时,可以结合 computed 函数向下共享响应式的数据。
如果父级节点共享的是响应式的数据,则子孙节点必须以.value 的形式进行使用。
共有 0 条评论