vue组件通信--注意事项及经验总结

原创 Fly丶 教程 vue专题 138阅读 2018-10-15 22:17:47 举报

组件间的通信是是实际开发中非常常用的一环,如何使用对项目整体设计、开发、规范都有很实际的的作用,我在项目开发中对此深有体会,总结下vue组件间通信的几种方式,讨论下各自的使用场景

文章对相关场景预览

  • 父->子组件间的数据传递
  • 子->父组件间的数据传递
  • 兄弟组件间的数据传递
  • 组件深层嵌套,祖先组件与子组件间的数据传递

文章相关技术预览prop、emit、bus、vuex、路由URL、provide/inject

注:以下介绍与代码环境: vue2.0+、vue-cli2

父->子组件间的数据传递

父子组件的通信是开发是最常用的也是最重要的,你们一定知道父子通信是用prop传递数据的,像这样:

注意项:

  1. 父组件传递数据时类似在标签中写了一个属性,如果是传递的数据是data中的自然是要在传递属性前加 v-bind: ,如果传递的是一个已知的固定值呢
    • 字符串是 静态 的可直接传入无需在属性前加 v-bind
    • 数字,布尔,对象,数组,因为这些是js表达式而不是字符串,所以即使这些传递的是静态的也需要加 v-bind ,把数据放到 data 中引用,
  2. 如果prop传到子组件中的数据是一个对象的话,要注意传递的是一个 对象引用 ,虽然父子组件看似是分离的但最后都是在同一对象下
    • 如果prop传到子组件的值只是作为初始值使用,且在父组件中不会变化赋值到 data 中使用
    • 如果传到子组件的prop的数据在父组件会被改变的,放到 计算属性 中监听变化使用。 因为如果传递的是个对象的话,只改变下面的某个属性子组件中是不会响应式更新的,如果子组件需要在数据变化时响应式更新那只能放到computed中或者用watch深拷贝deep:true才能监听到变化
    • 当然如果你又需要在子组件中通过prop传递数据的变化做些操作,那么写在computed中会报警告,因为计算属性中 不推荐有任何数据的改变 ,最好只进行计算。如果你非要进行数据的操作那么可以把监听写在 watch (注意deep深拷贝)或者使用computed的 getset 如下图:

  • 但问题又来了,如果你传进来的是个对象,同时你又需要在子组件中操作传进来的这个数据,那么在父组件中的这个 数据也会改变因为你传递的只是个引用 , 即使你把prop的数据复制到 data 中也是一样的,无论如何赋值都是引用的赋值, 你只能对对象做深拷贝创建一个副本才能继续操作 ,你可以用JSON的方法先转化字符串在转成对象更方便一点,
  • 所以在父子传递数据时要先考虑好数据要如何使用,否则你会遇到很多问题或子组件中修改了父组件中的数据,这是很 隐蔽 并且很危险的

子->父组件间的数据传递

在vue中子向父传递数据一般用$emit自定义事件,在父组件中监听这个事件并在回调中写相关逻辑

那么问题来了,我是不是真的有必要去向父组件返回这个数据,用自定义事件可以在当子组件想传递数据或向子组件传递的数据有变化需要重新传递时执行,那么另外一种场景, 父组件需要子组件的一个数据但子组件并不知道或者说没有能力在父组件想要的时候给父组件 ,那么这个时候就要用到组件的一个选项 ref

<editor ref="editor" @editorEmit='editorEmit'></editor>

  • 父组件在标签中定义ref属性,在js中直接调用 this.$refs.editor 就是调用整个子组件,子组件的所有内容都能通过ref去调用,当然我们并不推荐因为这会使数据看起来非常混乱,
  • 所以我们可以在子组件中定义一种专供父组件调用的函数, ,比如我们在这个函数中返回子组件data中某个数据,当父组件想要获取这个数据就直接主动调用ref执行这个函数获取这个数据,这样能适应很大一部分场景,逻辑也更清晰一点
  • 另外,父向子传递数据也可以用ref,有次需要在一个父组件中大量调用同一个子组件,而每次调用传递的prop数据都不同,并且传递数据会根据之后操作变化,这样我需要在data中定义大量相关数据并改变它,我 可以直接用ref调用子组件函数直接把数据以参数的形式传给子组件 ,逻辑一下子清晰了
  • 如果调用基础组件可以在父组件中调用ref执行基础组件中暴露的各种功能接口,比如显示,消失等

兄弟组件间的数据传递

vue中兄弟组件间的通信是很不方便的,或者说不支持的,那么父子组件中都有什么通信方式呢

  • 路由URL参数
    • 在传统开发时我们常常把需要跨页面传递的数据放到url后面,跳转到另外页面时直接获取url字符串获取想要的参数即可,在vue跨组件时一样可以这么做,
  在跳转后的组件中用$route.params.id去获取到这个id参数为12,但这种只适合传递比较小的数据,数字之类的
  • Bus通信

在组件之外定义一个bus.js作为组件间通信的桥梁,适用于比较小型不需要vuex又需要兄弟组件通信的

  1. bus.js中添加如下

import Bus from './bus.js'
export default {
methods: {
bus () {
Bus.$emit('msg', '我要传给兄弟组件们')
}
}
}

import Bus from './bus.js'
    export default {
        mounted() {
           Bus.$on('msg', (e) => {
             console.log(e)
           })
         }
       }

// 父级组件提供 'foo'
var Provider = {
provide: {
foo: 'bar'
},
// ...
}

// 子组件注入 'foo'
var Child = {
inject: ['foo'],
created () {
console.log(this.foo) // => "bar"
}
}

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复