乐趣区

关于前端:在-Vue-中使用-attrs-构建高级组件

本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。
更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi,蕴含一线大厂面试残缺考点、材料以及我的系列文章。

这节课,咱们来看下 Vue3 中的 $attrs 属性。首先,咱们会介绍它的用处以及它的实现与 Vue2 有哪些不两同点,并通过事例来加深对它的了解。

真正了解了 $attrs 属性有助于咱们构建易于应用和可扩大的高级组件

什么是 $attrs

$attrs 定义,Vue2 与 Vue3 是不一样的,这里咱们次要来介绍 Vue3 的版本:

$attrs 对象蕴含了除组件所申明的 props 和 emits 之外的所有其余 attribute,例如 class,style,v-on 监听器等等。

$attrs 也能够被看作是一个安全网,它能够捕捉任何咱们没有在组件中申明的货色。咱们思考一个只有一个属性和事件处理程序的组件,如下所示:

<template>
  <h1 @click="$emit('custom',' 扭转题目 ')">{{title}}</h1>
</template>
<script>
export default {
  name: 'Example',
  props: ['title'],
  emits: ['custom'],
}
</script>

如果在父组件中像上面这样实例化下面的组件:

<template>
  <div id="app">
    <SimpleEvent
      id="myId"
      class="myClass"
      data-cy="cypress-testing"
      @blur="onBlur"
      title="测试 $attrs"
      description="没有申明 props"
      @custom="onCustom"
    />
  </div>
</template>

<script setup>
import SimpleEvent from './components/Button.vue'

const onBlur = () => {// todo}
const onCustom = () => {// todo}

</script>

如果在组件中把 $attrs 打印进去,咱们会失去如下内容:

{
  id: 'myId',
  class: 'myClass',
  'data-cy': 'cypress-testing',
  description: '没有申明 props',
  onBlur: () => { // todo} 
}

下面这些信息,感觉没啥用,其实不然,咱们上面会介绍如何利用这些信息。

attrs V3 vs $attrs V2

这大节,咱们来看下 Vue2 与 Vue3 中的 attrs 属性的区别,先来看张图:

与 Vue2 的区别次要有:

  • 自定义事件放在 @listerner 对象中
  • 不蕴含 class 属性

而 Vue3 中的 attrs 对象蕴含了除组件所申明的 propsemits 之外的所有其余 attribute,这有利于咱们方便使用这些属性。

上面咱们来看些事例。

事例

事例地址:https://stackblitz.com/edit/v…

首先咱们创立一个 Slider 组件,内容如下所示:

<template>
  <input 
    type="range"  
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
    class="slider__input" />
</template>

<script>
export default {
  name: "Slider-1",
  props: {modelValue: [Number, String],
  }
};
</script>
<style lang="scss">
// 这里省略一堆款式,自行看事例
</style>

下面代码咱们创立一个 slider,还实现了一个双向绑定。而后能够像上面这样应用该组件:

 <Slider-1 v-model="value" />

增加一些属性

目前咱们的 Slier 组件还很简略,不太符合实际状况。所以,咱们增加几个属性(min, max, class, id, data-cy, @keydownaria-label)。

  <Slider-1
      v-model="value"
      min="0"
      max="50"
      class="blue_slider"
      id="special_id"
      data-cy="cypress-slider"
      @keydown="() => true"
      aria-label="Example slider"
    />

运行后,通过管制查看元素,咱们能够看下,咱们新加的属性都被增加到了 HTML 元素上了:

看到这里,大家可能有疑难了,既然所有的 “ 非属性 / 事件 ” 属性都曾经主动利用于外部的 HTML 元素,为什么还要对 $attrs 做这么大的介绍?

增加题目和值

新增需要:作为一个滑块的使用者,用户心愿可能看到一个题目,以及它在屏幕上显示的数字模式的值。

咱们在调整一下 Slider 组件,内容如下:

// Slider-2.vue

<template>
  <div class="slider">
    <h1>{{title}}</h1>
    <input 
      type="range" 
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)"
      class="slider__input" />
      <div>Value: {{value}}</div>
  </div>
</template>

<script>
export default {
  name: "Slider-2",
  props: {modelValue: [Number, String]
    title: [String],
    value: [Number, String],
  }
};
</script>

乍一看,如同没啥问题,但如果咱们仔细观察,能够看到有些货色是不对的。

首先,Slider 不是蓝色的。第二,value 远远超过了 50,最初,检查一下 HTML,会看到咱们所有的额定属性(min, max, data-cy)都被调配给了根元素,而不是咱们的 input 元素。

解决上述问题的最好办法是找到一种办法,将所有的属性、类、参数和事件间接 “ 利用 ” 到 input 字段上,而不需咱们手动的一个个申明。这就是 $attrs 出场的中央。

$attrs 救场

在本文的结尾,咱们介绍了 $attrs。它是一个寄存所有 “ 未声明 ” 的属性和事件的中央,而这正是咱们须要解决的问题。

要应用这个性能,咱们只需将 $attrs 属性利用于一个或多个 HTML 元素,应用 v-bind 操作符。

<template>
  <div class="slider">
    <h1>{{title}}</h1>
    <input 
      type="range"  
      v-bind="$attrs"
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)"
      class="slider__input" />
      <div>Value: {{modelValue}}</div>
  </div>
</template>

在组件中,咱们应用 attrs 充当桥梁,将所有的属性(类、属性、属性和自定义事件)复制到一个或多个元素上。Slider 组件又回到了失常模式上了。

还有一个问题 – 咱们增加的属性不仅被调配给了 input 元素上,也调配给了 root 元素。

通常状况下,这可能对界面没啥影响,但有的属性的确会生产一些副作用,上面,咱们来解决这个问题。

inheritAttrs: false

默认状况下,任何被传递给组件的额定参数都会主动利用于根元素(以及所有有 $attrs 绑定的元素)。

为了敞开这个性能,并管制哪些元素可承受这个额定的属性,咱们能够应用一个名为 inheritAttrs 的标记,并将其设置为 false

通过这样的扭转,咱们的 HTML 就变得丑陋且洁净了。所有的额定属性都只作用于 input 元素。

编辑中可能存在的 bug 没法实时晓得,预先为了解决这些 bug, 花了大量的工夫进行 log 调试,这边顺便给大家举荐一个好用的 BUG 监控工具 Fundebug。

交换

有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

退出移动版