Vue 学习笔记:$attrs 和 $listeners 的用法

Posted 毕小宝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 学习笔记:$attrs 和 $listeners 的用法相关的知识,希望对你有一定的参考价值。

文章目录

背景

学习 vueAdmin-template 这个项目时,看到两个属性 v-bind="$attrs"v-on="$linteners",于是就这两个属性的用法作了一下深入了解,通过一个简单的 demo 测试并理解了它们的用法。

我们知道,向子组件传递数据,是通过 v-bind 子类组件定义的 props 属性完成的,这只适用于单向、两层组件之间。同样地,事件传递也是在父组件中用 v-on 给子组件绑定事件,然后在子组件中通过 this.$emit 触发的、以达到修改父组件数据的目的。

那么,在多层嵌套组件中,顶层组件和最底层组件之间如何进行数据传递和事件触发呢?比如,A 组件引用了 B 组件,而 B 组件又引用了 C 组件,那么怎么在 A 中将数据传给 C ;在 C 中,怎么触发 A 中的方法呢?这就是 $attrs$listeners 的作用了。

$attrs

$attrs 是一个内置属性,指父组件传递的、除了自己定义的 props 属性之外的所有属性。例如 A 组件引用 B 组件,并为其绑定了三个属性 foo、coo、coo1:

<child-dom
  :foo="foo"
  :coo="coo"
  :coo1="foo"
  v-on:eventBindOnB="eventMethodInA"
>

B 组件【child-dom】中定义的属性为 props: ['foo', 'coo1'] 那么在 B 组件中打印 $attrs,就是除了 props 之外的属性 coo 。此时,B 又引用了组件 C 并向其传递了一个属性 coo :

<child-dom-child 
:coo="coo1" 
msg="B 组件的配置,但是 C 组件没有定义"
v-bind="$attrs" 
v-on="$listeners" 
@change="eventMethodInB"></child-dom-child>

而 C 组件【child-dom-child 】中定义了 props: ['coo', 'coo1'],此时在 C 组件中打印的$attrs是空的。学习所参考的项目中,需要在 B 组件中将 $attrs 绑定给 C ,但是测试发现,去掉这个绑定操作,C 中默认也是有$attrs 属性,也可以得到父组件的值。

$listeners

$listeners 包含了作用在这个组件上所有的监听器,即父组件绑定的全部监听事件,通过 v-on="$listeners",可以将这些事件绑定给它自己的子组件。

前面例子中 ,B 组件 为 C 组件最终绑定的监听事件等于 A 为 B 绑定的 eventBindOnB 事件,加上 B 为 C 绑定的 change 事件,可以在 C 中触发任何绑定在 C 上的事件。

C  的事件 = A 的监听事件 eventBindOnB +  B 的监听事件 change

此时,在 C 组件中定义一个按钮,就可以触发 A 组件的方法了:

元素定义:
<button @click="triggerMethodInA">点击</button>

方法定义
triggerMethodInA() 
   this.$emit('change')  //触发 B 的监听事件
   this.$emit('eventBindOnB') // 触发 A 的监听事件

A 组件中的方法定义:

methods: 
  eventMethodInA() 
    this.coo = 'I have been changed'
    this.msg = 'I have been changed11'
    console.log('change is trigger.')
  

B 组件的方法定义:

methods: 
  eventMethodInB() 
   // this.coo1 = 'B Component change it '
    console.log('change is trigger.')
  

据此,就完成了嵌套组件中,底层触发顶层事件的逻辑了。
点击 C 组件的按钮,最终调用 A 的某个方法,完成对 A 数据的修改操作:

启示录

props 是父子组件传递数据的方式,是由父组件单向控制子组件属性的,所以不能在子组件中直接修改自己的 props 属性,否则 vue 会报错:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten 
whenever the parent component re-renders. 
Instead, use a data or computed property based on the prop's value. 
Prop being mutated: "coo1"

总结一下嵌套组件的数据和事件触发过程:

本文参考 这篇文章 的案例,完成对 $attrs$listeners 用法的整理。

通过敲代码,熟悉了一些 ESLint 的规范,也顺便验证了一下老祖宗的智慧:无他,唯手熟能尔!

以上是关于Vue 学习笔记:$attrs 和 $listeners 的用法的主要内容,如果未能解决你的问题,请参考以下文章

vue $attrs、$listeners使用

Vue 警告 $listeners 和 $attrs 是只读的

Vue2.x $attrs和$listeners

Vue2.x $attrs和$listeners

vue$attrs和$listeners的使用

vue中的$attrs和$listener简介