Vue 学习笔记:$attrs 和 $listeners 的用法
学习 vueAdmin-template 项目时,看到两个属性 v-bind="$attrs" 和v-on="$linteners",于是就这两个属性的用法作了一下深入的了解,通过一个简单的 demo 测试并理解了它们的用法和作用。我们知道,向子组件传递数据,是通过 v-bind 一个子类组件定义的 props 属性完成的,这只使用于单向两层组件引用之间。同样地,事件传递也是在父组件中用 v...
背景
学习 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 的规范,也顺便验证了一下老祖宗的智慧:无他,唯手熟能尔!
更多推荐
所有评论(0)