$attrs和$listenners

Vue2.x 中的 a t t r s 和 attrs和 attrslisteners

或许很多Vue小白跟我一样, 在之前不太了解 a t t r s 和 attrs和 attrslistenners这两个API是干嘛的, 甚至没有听过或者使用过。下面我来浅述一下我对这两个API的理解。

下文将基于下面这张图片来进行解释,现在我们有三个组件, 组件之间的结构关系如下图所示: A:爷爷组件、B:父亲组件、C:儿子组件

image-20221004143415339

$attrs

为什么要用$attrs?

场景: 现在组件的结构如上图所示,我们要实现由A组件到C组件之间的数据通信,有几种实现方式?

  1. 像我一样的小白或许刚好学了Props,此时一股脑将所有的属性写在B组件的Props中,这个方案固然可行,但是如果C组件下面还有组件呢?C的子孙千千万,B的Props中的属性也将变成千千万。不得不说B作为父亲的压力是真的大,不仅仅要养活C,还要养活C将来可能存在的千万子孙。这种解决方案无疑给后续的代码维护造成了比较大的阻碍。
  2. 或许学完了Props的小伙伴们又说了,那我们是不是可以借助其它工具?例如VueX这样的工具来实现,没错!VueX当然也可以实现以上场景,但是如果C中会用到的属性值很少,那么此时使用VueX来介入这样的问题,是否有点 ‘大动干戈’ 了呢?

能够解决(父→子)通信这类问题的手段有很多,正所谓没有最好的解决方案, 只有更适合的解决方案。在本文中主要踢一下$attrs这个API的使用。

怎么使用$attrs?

在vue2.4中,为了更好的解决上面这类场景的问题,引入了$attrs这一API来帮助咱开发者来解决这个问题。话不多说上代码:

<!-- 爷爷组件A -->
<template>
  <div>
    <my-father :foo="foo"
      :bar="bar"
      :fatherName="'老王'"
      :sonName="'小王'">
    </my-father>
  </div>
</template>
<script>
import MyFather from "./MyFather.vue";
export default {
  components: {
    MyFather,
  },
  data () {
    return {
      foo: "foo",
      bar: "bar",
    };
  },
};
</script>
<!-- 父亲组件B -->
<template>
  <div>
    <p>----------------------------</p>
    <p>father中的foo:{{ foo }}</p>
    <p>father中的attrs: {{ $attrs }}</p>
    <my-son v-bind="$attrs"></my-son>
  </div>
</template>
<script>
import MySon from "./MySon.vue";
export default {
  props: ["foo", "fatherName"],
  components: {
    MySon,
  },
  created () {
    console.log('father组件中的$attrs:', this.$attrs);
  }
};
</script>
<!-- 孙子组件C -->
<template>
  <div>
    <p>----------------------------</p>
    <p>son中的bar:{{ bar }}</p>
    <p>son中的$attrs:{{ $attrs }}</p>
  </div>
</template>
<script>
export default {
  props: ["bar"],
  created () {
    console.log('son组件中的$attrs:', this.$attrs);
  }
};
</script>

页面显示如下:

image-20221004151545963

从上面程序运行的结果, 相信能够看到$attrs的威力了, 它能够让咱们在解决父子通信、爷孙通信这类问题场景的时候更加优雅。毕竟优雅永不过时嘛

$listeners

爷爷 → 孙子 讲完了, 接下来看看咱们如何优雅地解决 爷爷 ← 孙子 的问题。

为什么要用$listenners?

场景: 现在组件之间的结构如最上面的图所示,我们要实现由C组件到A组件之间的数据通信,有几种实现方式?

  1. 可以在C组件中使用$emit()方法, 抛出一个事件给B组件, B组件再调用$emit()方法抛给A组件, 像这样一层一层往上传递。在组件关系、组件功能都不复杂的情况下,使用这种方法可以快速完成子组件到父组件之间的通信。
  2. 通过VueX来实现父子组件通信
  3. 父组件通过ref来调用子组件的方法

能够解决(父←子)通信这类问题的手段有很多,正所谓没有最好的解决方案, 只有更适合的解决方案。接下来主要踢一下$listenners这个API的使用。

怎么使用$listenners?

话不多说, 上代码:

<!-- 爷爷组件A -->
<template>
  <div>
    <my-father :foo="foo" @updateFoo="update" />
  </div>
</template>
<script>
import MyFather from "./MyFather.vue";
export default {
  components: {
    MyFather,
  },
  data () {
    return {
      foo: "foo",
    };
  },
  methods: {
    update (newValue) {
      this.foo = newValue
      console.log("update success");
    }
  }
};
</script>
<!-- 父亲组件B -->
<template>
  <div>
    <p>father中的foo:{{ foo }}</p>
    <my-son v-bind="$attrs" v-on="$listeners" />
  </div>
</template>
<script>
import MySon from "./MySon.vue";
export default {
  props: ["foo"],
  inheritAttrs: false,
  components: {
    MySon,
  },
};
</script>
<!-- 孙子组件C -->
<template>
  <div>
    <button @click="sonFun">更新foo</button>
  </div>
</template>
<script>
export default {
  props: ["bar"],
  methods: {
    sonFun () {
      this.$emit("updateFoo", "oof");
      console.log("sonFun!!!");
    }
  }
};
</script>

代码运行的效果如下所示:

$listeners

通过观察我们发现, 由C组件到A组件之间的通信仅用到了一次 e m i t ( ) , 这一小小的举动让我们的组件通信变得更加优雅了 , 我们只需要在 B 组件使用 C 组件的地方加上一句 ‘ v − o n = " emit(), 这一小小的举动让我们的组件通信变得更加优雅了, 我们只需要在B组件使用C组件的地方加上一句`v-on=" emit(),这一小小的举动让我们的组件通信变得更加优雅了,我们只需要在B组件使用C组件的地方加上一句von="listeners"`就可以让A组件监听到C组件抛出的事件。

看完本文后是否对$attrs$listenners 有了深刻的认识呢? 😁😁😁

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值