耀极客论坛

 找回密码
 立即注册
查看: 806|回复: 0

Vue封装组件利器之$attrs、$listeners的使用

[复制链接]

193

主题

-17

回帖

276

积分

中级会员

Rank: 3Rank: 3

积分
276
发表于 2022-5-8 01:44:23 | 显示全部楼层 |阅读模式
  vue通信手段有很多种,props/emit、vuex、event bus、provide/inject等,还有一种通信方式,那就是$attrs和$listeners,下面这篇文章主要给大家介绍了关于Vue封装组件利器之$attrs、$listeners使用的相关资料,需要的朋友可以参考下

前言
  多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。但仅仅是传递数据,不做中间处理,使用 vuex 处理,未免有些大材小用了。所以就有了 $attrs 、 $listeners两个属性 ,通常配合 inheritAttrs 一起使用。

$attrs
  从父组件传给自定义子组件的属性,如果没有 prop 接收会自动设置到子组件内部的最外层标签上,如果是 class 和 style 的话,会合并最外层标签的 class 和 style。
  如果子组件中不想继承父组件传入的非 prop 属性,可以使用 inheritAttrs 禁用继承,然后通过 v-bind="$attrs" 把外部传入的 非 prop 属性设置给希望的标签上,但是这不会改变 class 和 style。
  inheritAttrs 属性 官网链接
  2.4.0 新增
  类型:boolean
  默认值:true
  详细:
  默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为普通的 HTML attribute 应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例 property $attrs 可以让这些 attribute 生效,且可以通过 v-bind 显性的绑定到非根元素上。
  注意:这个选项不影响 class 和 style 绑定。

例子:
  父组件
  1. ‹template>
  2.   ‹my-input
  3.       required
  4.       placeholder="请输入内容"
  5.       type="text"
  6.       class="theme-dark"
  7.   />
  8. ‹/template>
  9. ‹script>
  10. import MyInput from './child'
  11. export default {
  12.   name: 'parent',
  13.   components: {
  14.     MyInput
  15.   }
  16. }
  17. ‹/script>
复制代码
  子组件
  1. ‹template>
  2.   ‹div>
  3.     ‹input
  4.         v-bind="$attrs"
  5.         class="form-control"
  6.     />
  7.   ‹/div>
  8. ‹/template>
  9. ‹script>
  10. export default {
  11.   name: 'MyInput',
  12.   inheritAttrs: false
  13. }
  14. ‹/script>
复制代码
  子组件中没有接受父组件中传过来的值,也没有绑定,但是有v-bind="$attrs"这个属性,他会自动接受并绑定
  inheritAttrs: false

  inheritAttrs: true


$listeners (官网解释)
  listeners: 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
  先上代码:这里只举例focue、input两个原生事件
  1. // 父组件
  2. ‹template>
  3.   ‹my-input
  4.       required
  5.       placeholder
  6.       class="theme-dark"
  7.       @focue="onFocus"
  8.       @input="onInput"
  9.   >
  10.   ‹/my-input>
  11. ‹/template>
  12. ‹script>
  13. import MyInput from './child'
  14. export default {
  15.   components: {
  16.     MyInput
  17.   },
  18.   methods: {
  19.     onFocus (e) {
  20.       console.log(e.target.value)
  21.     },
  22.     onInput (e) {
  23.       console.log(e.target.value)
  24.     }
  25.   }
  26. }
  27. ‹/script>
复制代码
  1. // 子组件
  2. ‹template>
  3.   ‹div>
  4.     ‹input
  5.         type="text"
  6.         v-bind="$attrs"
  7.         class="form-control"
  8.         @focus="$emit('focus', $event)"
  9.         @input="$emit('input', $event)"
  10.     />
  11.   ‹/div>
  12. ‹/template>
  13. ‹script>
  14. export default {
  15.   name: 'MyInput',
  16.   inheritAttrs: false
  17. }
  18. ‹/script>
复制代码
  这样绑定原生事件很麻烦,每一个原生事件都需要绑定,但用v-on="$listeners"就会省事很多
  1. ‹input
  2.         type="text"
  3.         v-bind="$attrs"
  4.         class="form-control"
  5. +       v-on="$listeners"
  6. -       @focus="$emit('focus', $event)"
  7. -       @input="$emit('input', $event)"
  8.     />
复制代码
  这样一行代码就能解决绑定所有的原生事件的问题

使用场景
  组件传值时使用: 爷爷在父亲组件传递值,父亲组件会通过$attrs获取到不在父亲props里面的所有属性,父亲组件通过在孙子组件上绑定$attrs 和 $listeners 使孙组件获取爷爷传递的值并且可以调用在爷爷那里定义的方法;
  对一些UI库进行二次封装时使用:比如element-ui,里面的组件不能满足自己的使用场景的时候,会二次封装,但是又想保留他自己的属性和方法,那么这个时候时候$attrs和$listners是个完美的解决方案。

总结
  到此这篇关于Vue封装组件利器之$attrs、$listeners使用的文章就介绍到这了,更多相关Vue封装组件$attrs、$listeners使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|耀极客论坛 ( 粤ICP备2022052845号-2 )|网站地图

GMT+8, 2023-3-24 13:29 , Processed in 0.083996 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表