vue组件之间的传值——中央事件总线与跨组件之间的通讯($attrs、$listeners)

vue组件之间的通讯有不少种方式,最经常使用到的就是父子组件之间的传值,可是当项目工程比较大的时候,就会出现兄弟组件之间的传值,跨级组件之间的传值。不能否认,这些均可以相似父子组件一级一级的转换传递,可是当项目比较大,功能比较复杂的时候,就会变得比较冗余,代码不利于维护;这时候可能会有不少人使用到vuex,可是若是项目中多个组件共享状态比较少,项目比较小,而且全局状态比较少,好像就没有使用vuex来管理数据的必要。vue

1、中央事件总线(eventBus)vuex

主要是经过在要相互通讯的兄弟组件之中,都注册引入一个新的vue实例,而后经过分别调用这个实例的事件触发和监听来实现通讯和参数传递,也就是咱们常说的bus车事件。性能

一、首先,全局注册一个新的vue实例,能够放在咱们经常使用的vue项目文件中this

js/event-bus.jsspa

import Vue from 'vue'
export default new Vue()

二、若是不想全局引用能够,在使用的vue文件里使用,举个例子:contentLeft.vue,contentRight.vue 须要将contentLeft.vue与contentRight.vue互相通讯code

contentLeft.vuecomponent

<template>
  <div>
    {{message}}
    <button @click="handleClick">test</button>
  </div>
</template>

<script>
import bus from '../../assets/js/event-bus'

export default {
  data () {
    return {
      message: 'this is content here'
    }
  },
  props: {
    con: {
      type: String
    }
  },
  components: {
    descripe
  },
  methods: {
    handleClick () {
      bus.$emit('getDate', 'brathers!')
    }
  }
}
</script>

contentRight.vue blog

<template>
  <div>
    {{message}}
    <p v-for="(item,index) in meslist" :key="index">{{item}}</p>
  </div>
</template>

<script>
import bus from '../../assets/js/event-bus'
export default {
  data () {
    return {
      message: '',
      meslist: []
    }
  },
  created () {
    bus.$on('getDate', (val) => {
      console.log(val)
      this.message = val
      // this.meslist.push(val)
    })
  },
  beforeDestroy () {
    // 组件销毁前须要解绑事件。不然会出现重复触发事件的问题!!!!!!!!!!!!!
    bus.$off('getDate')
  }
}
</script>

当点击contentLeft的按钮的时候,contentRight的message值就获取到了总left中传过来的'brothers'生命周期

优势:经过bus事件方法能够简单快捷的进行组件之间的传值,在项目不大的时候,减小了对vuex的依赖事件

缺点:一、bus事件对生命周期比较严谨,当你bus.$emit发送事件时,若是兄弟组件还不存在,当真正打开兄弟组件时,此时在created里面bus.$on是监听不到传递的值的

二、bus事件不会随着组件的关闭而自行销毁,因此当路由切换时,bus事件会不停的触发,若是数据量比较多的时候,可能会比较影响性能吧,因此须要及时销毁所绑定的bus事件

2、跨组件之间的通讯

vue2.4以后,跨组件之间的通讯能够经过$attr和$listeners来实现

举个例子,father.vue  child.vue  grandChild.vue

father.vue组件中传值

<template>
  <div class="about">
    <p>子组件给父组件传值,父组件再给父组件传值</p>
    <child
      :con="con"
      :son="son"
      @getCData = "getCData"
    ></child>
  </div>
</template>

<script>
import child from './components/child'

export default {
  data () {
    return {
      test: 'test',
      con: 'child',
      son: 'child-child'
    }
  },
  components: {
    child
  },
  methods: {
    getGrandChildData (val) {
      this.son = val
      console.log('这是来自grandchild组件的数据:' + val)
      console.log(this.son)
    }
  }
}
</script>

child.vue组件中设置grandChild组件的$attr和$listner属性

<template>
  <div>
    {{message}}
    <i class="get-data">{{con}}</i>
    <grandChild v-bind="$attrs" v-on="$listeners"></grandChild >
    <button @click="handleClick">test</button>
  </div>
</template>

<script>
import grandChild from './grandChild '

export default {
  data () {
    return {
      message: 'this is content here'
    }
  },
  props: {
    con: {
      type: String
    }
  },
  components: {
    grandChild 
  }
}
</script>

grandChild.vue组件能够经过$attr监听到爷爷级组件的值,再经过触发事件向爷爷级组件传递修改值

<template>
  <div>
    {{list}}
    <p class="get-data">{{$attrs.son}}</p>
    <input type="text" v-model="$attrs.son">
    <button @click="passData($attrs.son)">按一下</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      list: 'ceshixia'
    }
  },
  methods: {
    passData (val) {
      // 触发事件,改变值爷爷级组件的值
      this.$emit('getGrandChildData', val)
    }
  }
}
</script>

以上就能够实现跨级组件之间的传值,能够引用到各类场景中去

相关文章
相关标签/搜索