阅读 594

vue高层次组件(组件多层嵌套)应用:$attrs 和 $listeners

在使用vue组件传参的时候,我们一般会使用props传参,在不同的需求下也会使用其他对应不同的方法处理传参以求更便捷高效。在我学习这些传参方法中,发现了一种使用较少(自认为)的冷门方法:$attrs 和$listeners

使用这种方法的情况是当我们在处理高层次组件也就是多层嵌套的组件时,如果父组件要给孙子组件甚至更下代组件传很多属性参数,子组件处在中间作为一种过渡将上层数据交给下层。如果使用props方法在子组件中需要接收大量的props,然后在交给下层,这样的话就显得很繁琐,而且代码看起来感觉很多余。

$attrs 和$listeners 就可以很好的解决这个问题,在过渡的子组件中仅仅只需在要传参的组件上加上v-bind="$attrs" 或 v-on="$listeners"就实现得以实现。

$attrs

根据官网的介绍,我对 $attrs 的理解是父组件给子组件传递的参数,如果不使用 props 接收参数,那么这些参数就会交给 vm 的 $attrs 属性。

我们看个例子:

这里定义了父子孙三个组件,父组件需要将这三个参数传给孙子组件。

父组件

<template>
  <div>
    father
    <Son :data1="data1"
      :data2="data2"
      :data3="data3" />
  </div>
</template>

<script>
import Son from "./Son.vue";
export default {
  name: "father",
  components: { Son },
  data() {
    return {
      data1: 1,
      data2: 2,
      data3: 3,
    };
  },
};
</script>复制代码

我们直接在子组件上通过 this.$attrs 打印一下:

image.png

可以发现能够打印出父组件的属性,那么直接使用v-bind="this.$attrs"传给孙子组件

子组件

<template>
  <div>
    son
    <Grandson v-bind="this.$attrs" />
  </div>
</template>复制代码

在孙子组件中直接将数据放到页面上

孙子组件

<template>
  <div>
    Grandson<br>
    {{ $attrs }}
  </div>
</template>复制代码

image.png

这样孙子组件就很轻松的拿到了父组件的属性,在组件层级多、属性多的情况下,就不用把所有属性都重复的接收传递,只需要一行v-bind="this.$attrs"就可以一次性全部接收,非常的方便。

还有值得注意的一点:

默认情况下 vue 会把父作用域的不被认作 props 的特性绑定 且作为普通的 HTML 特性应用在子组件的根元素上。在我们使用这种方法的时候就会出现这种情况。官方原话是传递的参数会“回退”且作为普通的 HTML 特性应用在子组件的根元素上,这个选项不影响 class 和 style 绑定。

image.png

虽然这可能不影响我们使用,但是最好还是将其去掉,不然在某些特殊情况可能会产生 bug。通过将inheritAttrs 设置成 false,这些默认行为将会被去掉。

这里只在孙子组件中设置,子组件不加对比:

<script>
export default {
  name: "Grandson",
  inheritAttrs: false,
};
</script>复制代码

image.png

可以看到孙子组件的元素上已经去掉了,子组件还在。

$listeners

如果要传很多的自定义方法,频繁在过渡的子组件中使用 $emit 就显得非常繁琐,使用 $listeners 也是同理,用法也相似,这里就不过多介绍,直接看例子。

父组件

<template>
  <div>
    father
    <Son @med1="med1"
      @med2="med2"
      @med3="med3" />
  </div>
</template>

<script>
import Son from "./Son.vue";
export default {
  name: "father",
  components: { Son },
  methods: {
    med1() {
      console.log(1);
    },
    med2() {
      console.log(2);
    },
    med3() {
      console.log(3);
    },
  },
};
</script>复制代码

子组件

<template>
  <div>
    son
    <Grandson v-on="this.$listeners " />
  </div>
</template>复制代码

孙子组件

export default {
  name: "Grandson",
  inheritAttrs: false,
  created() {
    this.$emit("med1");
    this.$emit("med2");
    this.$emit("med3");
  },
};复制代码

结果:

image.png

以上就是所有内容了,有道是技多不压身,虽然这种方法可能用得不多,但存在即合理,学会得多总不会错,若有说明不到位的地方希望多多指正,再会。


作者:执刀人
链接:https://juejin.cn/post/7025796556397740062


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐