③vue组件之间的通信(不包含vuex)

154 阅读1分钟

第三种:隔代组件之间的传值

当我们由需求,需要在隔代组件之间进行传值的时候,是不是只需要使用props和$emit一层层地进行传递就好了?是的,这样做完全没有问题,但是vue给我们提供了一种更为优雅的解决方案,那就是$attrs和$listeners,首先我们来看官方API是怎么对这两个属性定义的:



这两个属性的定义 读起来就非常的拗口,但先抓取内容中的关键词,$attrs:不作为prop被识别的特性绑定、传入内部组件;$listener:父作用域中事件监听器、传入内部组件。总结起来就是,从父组件接收属性和方法,传递到内部组件中去。我们来看一下代码是怎样实现的:

grandfather组件(最外层的组件)

<template>  <div class="grand-father">    <h2>{{name}}</h2>    <p>{{desc}}</p>    <p>{{price}}</p>    <child      :desc="desc"      :price="price"      @setPrice="setPrice"/>  </div></template><script>import child from '@/components/child'export default {  name: 'grandfather',  components: {child},  data () {    return {      name: '祖父组件中的名字',      desc: '我们将desc和price传递到孙代组件中去,并在孙代节点中修改price的值',      price: 10    }  },  methods: {    setPrice (val) {      this.price = val    }  }}</script><style></style>

这里我们将后代组件需要的属性和方法传递到father组件(第一级嵌套组件)中,接下来是father组件的代码

<template>  <div>    <h4>{{name}}</h4>    <son      v-bind="$attrs"      v-on="$listeners"/>  </div></template><script>import son from '@/components/grandson'export default {  name: 'father',  components: {    son  },  data () {    return {      name: '这里是父代节点'    }  },  methods: {}}</script><style></style>

在father组件中,除去props接收到的属性使用v-bind="$attrs"直接打包传递到孙代组件中去,使用v-on="$listener"将定义的方法打包传递到孙代节点中去,这里不需要使用,就是不必要在这里接收,再来看grandson的代码

<template>  <div class="son">    <h5>{{name}}</h5>    <p>{{$attrs.desc}}</p>    <input type="text"      @input="changePrice">  </div></template><script>export default {  name: 'son',  data () {    return {      name: '这里是孙代节点'    }  },  methods: {    changePrice (e) {      this.$emit('setPrice', e.target.value)    }  },  created () {    console.log(this.$attrs)    console.log(this.$listeners)  }}</script><style></style>

在grandson组件(内部组件)中,我们可以使用$attrs接收到所有来自最外层组件所传递的属性,可以使用$emit来调用最外层监听的事件,这样我们就完成了隔代组件之间的通信