vue组件之间的数据传递方法
栏目: JavaScript · 发布时间: 5年前
内容简介:在父组件中,可以通过子组件标签属性的形式将数据或者函数传给子组件,子组件通过props去读取父组件传过来的数据引用类型的props,我们可以在子组件中直接修改引用类型属性的值(如:this.obj.id='3',会生效),但是不能直接改变引用类型存储的地址值(如:this.obj = {id: '3'}),会发出警告。虽然子组件可以直接修改父组件的状态值,但我们不建议这样做,我们希望所有的 prop 都使得其父子 prop 之间形成了一个
(1)props属性:
在父组件中,可以通过子组件标签属性的形式将数据或者函数传给子组件,子组件通过props去读取父组件传过来的数据
-
用法
-
父组件传数据给子组件:
-
一般的属性值都是用来给子组件展示的
-
-
子组件传数据给父组件
-
属性值为函数类型的,一般是用来子组件向父组件传递数据,子组件通过调用父组件传过来的函数,可以修改父组件的状态数据
-
-
-
缺点:
-
隔层组件间传递: 必须逐层传递(麻烦)
-
兄弟组件间: 必须借助父组件(麻烦)
-
-
注意:
//子组件获取父组件传过来的值 props: { obj: {//obj为{id:'2'} type: Object } }复制代码
引用类型的props,我们可以在子组件中直接修改引用类型属性的值(如:this.obj.id='3',会生效),但是不能直接改变引用类型存储的地址值(如:this.obj = {id: '3'}),会发出警告。
虽然子组件可以直接修改父组件的状态值,但我们不建议这样做,我们希望所有的 prop 都使得其父子 prop 之间形成了一个 单向下行绑定 :父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
脏数据问题: 如v-model是实现了双向绑定,通过v-model更改数据,会更改父组件的数据,导致脏数据
解决方法:
利用计算属性的set和get,在set中需实现子组件调用父组件的方法,确保数据流向是单向的
computed:{ msg: { get(){ return this.data }, set(){ this.$emit('EventName', this.data) } }}复制代码
(2)vue自定义事件:
-
方式1: 给子组件标签绑定事件监听
-
子组件向父组件的通信方式
-
功能类似于function props
-
通过在 父组件 中给子组件标签绑定自定义事件的监听,再由子组件触发事件,实现子组件向父组件传递数据的方法,事件名必须一致,且不能有大写字母,
v-on
事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的)// 方式一: 通过v-on绑定 <component @delete_todo="deleteTodo"/> // 方式二: 通过$on()绑定 this.$refs.xxx.$on('delete_todo', function (todo) { this.deleteTodo(todo)}) 通过this.$emit('delete_todo', todo)触发事件复制代码
-
-
不适合隔层组件和兄弟组件间的通信
-
注意:
-
在组件标签上绑定事件,会被解析为vue自定义事件
-
在普通的标签上绑定事件,会被解析为DOM事件
<--! 表示在组件component绑定了一个名为click的vue自定义事件, 相当于做了vm.$on('click',fn) 注意:不是常规理解的点击事件,这里与点击无关,只是名字刚好是click, 当然实际操作中不建议取这类特殊的名字 --> <component @click="fn"/> <--! 表示在div上绑定一个click的点击事件,是DOM事件 --> <div @click="fn"/>复制代码
-
-
-
方式2: 通过单独的vm对象绑定监听/分发事件
-
任意组件间通信(类似于pubsub)
-
创建一个公用的vm对象
import Vue from 'vue'export default new Vue()复制代码
-
在接收消息的组件,绑定监听
import vm from './vm.js'mounted(){ vm.$on('delete_todo', function (todo) { this.deleteTodo(todo) })}复制代码
-
在发送消息的组件,触发事件
vm.$emit('delete_todo', todo)复制代码
-
-
事件总线(EventBus),其实跟上面的用法一样,这里是把vm实例绑在了Vue的显示原型上
//点击任意一个组件,其他组件的值跟着变化,利用总线去实现兄弟之间的通信 Vue.prototype.bus = new Vue() var vm = new Vue({ el:"#app" }) //v-a组件 Vue.component('v-a', { template:'<div @click="handle">{{msg}}</div>', data(){ return { msg: 'v-a' } }, mounted () { //绑定事件监听 this.bus.$on('bus',(msg)=>{ this.msg = msg }) }, methods: { handle () { //触发事件 this.bus.$emit('bus', this.msg) } }}) //v-b组件 Vue.component('v-b', { template:'<div @click="handle">{{msg}}</div>', data(){ return { msg: 'v-b' } }, mounted () { //绑定事件监听 this.bus.$on('bus',(msg)=>{ this.msg = msg }) }, methods: { handle () { //触发事件 this.bus.$emit('bus', this.msg) } }})复制代码
-
(3) 消息的订阅和发布(pubsub)
-
适用于任何关系的组件间的通信
-
缺点:相对于vuex,管理不够集中
-
用法:
-
引入pubsub-js库
-
在接收消息的组件订阅消息(subscribe)
PubSub.subscribe('name',(name,data)=>{})复制代码
-
在发送消息的组件发布消息 ( publish)
PubSub.publish('name',data)复制代码
-
-
其他用法可以参考官方API文档,这里不细说
(4)vuex
vuex是专门为vue.js应用程序定义的状态管理模式,当多个组件需要共享数据时,我们一般用vuex去管理状态数据,实现多个组件间的相互通信
vuex的核心
-
state:存放数据
-
mutations:修改数据
-
actions:提交mutation,修改数据
-
getters:存放数据,类似于vue的计算属性
知道了这几个核心概念后,我们还需要知道怎么合理使用他们
-
如何从仓库store读取数据
-
state
从store的实例中我们可以通过store.state去获得状态数据,为了使得store可以全局使用,我们需要通过Vue.use(Vuex),将vuex注给所有vue子的组件,Vue.use回去调用插件的install方法,将stroe绑到Vue.prototype,这样Vue的实例对象都能通过vm.store获取或操作仓库的数据组件内通过this.$store.state可以获得
state:{ data: 0 }复制代码
-
getters
有些状态熟悉需要根据其他状态属性计算而动态获得,一般都是存在getters中,组件通过调用this.$store.getters
Getter 接受 state 作为其第一个参数
getters:{ data2(state){ return state.data+1 } }复制代码
-
-
如何修改仓库store的数据
-
mutations (同步修改)
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,接受 state 作为第一个参数 ,mutation接收提交载荷,第二个参数为载荷,在大多数情况下,载荷应该是一个对象 ,这样可以接收多个数据
mutations:{ mutationType:(state,data)=>{ state.data = data } }复制代码
-
actions (异步修改)
在action中提交mutation,组件通过store.dispatch触发
因为vue的调试 工具 无法检测到mutations的异步变化,所以我们如果需要异步修改状态数据,一般是放在action去异步获取到数据后再提交mutation,确保vue的调试工具可以检测到,mutation的变化
-
-
注意点 :
当组件需要给vue中的状态数据添加属性时,通过obj.的形式无法实现
因为Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:
-
我们最好提前在 store 中初始化好所有所需属性。
-
当需要在对象上添加新属性时,我们应该
-
使用
Vue.set(obj, 'newProp', 123)
, 或者 -
以新对象替换老对象。例如,利用 stage-3 的对象展开运算符,我们可以这样写:
state.obj = { ...state.obj, newProp: 123 }复制代码
-
-
优化
-
import {mapState,mapGetters,mapMutations,mapActions} from "vuex";使得在使用vuex时,组件可以写的更加的简洁
-
数据比较多的时候,使用module
-
使用常量存放mutation_type
-
优点:
-
多组件共享状态(数据的管理)
-
组件间的关系也没有限制
-
功能比pubsub强大, 更适用于vue项目
(5) slot插槽
-
父向子通信
-
通信是带数据的标签
-
注意: 标签是在父组件中解析
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- VUE父子组件传递数据
- Vue 中父子组件数据传递
- Vue使用props父子组件传递数据
- 【开发经验】Flutter组件的事件传递与数据控制
- Vue 中,如何将函数作为 props 传递给组件
- 将多个属性传递给 Vue 组件的几种方式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。