组件库开发—— attrs妙用 和 双向绑定 | 青训营笔记

199 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 15 天

input组件

input组件相对来说比较容易,虽然容易但是依然有值得记录的点。input组件是可以让我们深度了解到双向绑定的实现原理。

$attrs

在实际使用组件库开发时,肯定会接触到 $attrs 这个属性。

这个属性在平时业务应该不常用,但是当你想进行高级组件的封装时,这个属性就是一把利器。

具体使用非常简单:v-bind: $attrs,只需要一行就能实现。

但我们还是深入了解一下这个属性,这样我们才能知己知己。

什么是$attrs?

$attrs,它的作用是将父组件的所有属性绑定到当前组件上。

在 Vue 中,有时父组件会给子组件传递大量的属性,但是可能有些属性子组件并不需要。如果要手动一一绑定这些属性,非常繁琐。这时候就可以使用 v-bind="$attrs

更详细点:

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

$attrs 也可以被看作是一个安全网,它可以捕获任何我们没有在组件中声明的东西。我们考虑一个只有一个属性和事件处理程序的组件

例子

当我们在input组件开发时,我们在调用组件一般是这样

<h-input v-model="input" placeholder="请输入内容"></h-input>

注意哦,这个placeholder并不是我设置的props接口,但是我们又知道input标签是带有这个属性的,因此我们可以通过$attrs,获取到这个参数,并且挂载到input标签上。

<input
class="h-input"
v-bind="$attrs"
:type="type"
:value="text"
:class="size"
ref="input"
@input.stop="handerInput"
@blur.stop="handlerBlur"
@focus.stop="handlerFocus" />

这样是不是就方便了很多?

这就是attrs的妙用之处。

双向绑定

v-model是vue中常见的语法糖,一般用于在表单元素(如 input、textarea 和 select)上实现双向数据绑定。

v-model 指令的工作原理是:在表单元素上监听输入事件并更新数据,在元素上渲染数据。实际上,它仅仅是在表单元素上绑定了 v-bind 和 v-on 的简写,所以 v-model 只能在表单元素上使用。

也就是说,在这个input组件中我们需要自己实现一个双向绑定。

实现双向绑定

双向绑定说白了就是用 v-on 和 v-bind 结合起来的语法糖

在vue3中,

当在自定义组件中使用v-model时,组件接收一个属性modelValue的值,然后通过触发update:modelValue事件来更新该值:

<h-input v-model="msg"></h-input>
<!-- 等价于 -->
<h-input :model-value="msg" @update:model-value="msg = $event"></h-input>
<!-- 建议命名按照kebab-cased规范,如:model-value,而不是modelValue -->

v-model 实现

根据上面的定义规则,我们可以这样实现一个自定义 input 组件:

// 实现1:自定义input组件
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">

// 传入参数
props: ['modelValue'],

// 使用
<h-input v-model="msg"></h-input>;


// 实现2
<input :value="value" @input.stop="handerInput">
props: ['modelValue'],
const value = ref()
const handerInput = (e: any) => {
  text.value = e ? e.target.value : "";
  emit("update:modelValue", Number(text.value));
};

v-model 参数

通过上面的示例我们发现 v-model 是接收属性modelValue的值,然后触发事件update:modelValue来更新该值,那么我们可不可以修改这个属性名modelValue呢?

其实我们只需要给v-model添加参数即可,比如:v-model:mv,这样就将modelValue换成了mv

<input :value="mv" @input="$emit('update:mv', $event.target.value)"> 
props: ['mv'],

// 使用:
<h-input v-model:mv="msg"></h-input>;

正是由于 vue3 中新增了 v-model 的参数传递,所以自定义组件可以同时支持多个v-model的绑定:

<input type="text" :value="firstName" @input="$emit('update:firstName', $event.target.value)"> 
<input type="text" :value="lastName" @input="$emit('update:lastName', $event.target.value)">

props: { firstName: String, lastName: String, },

// 使用:

<h-input v-model:first-name="firstName" v-model:last-name="lastName"></h-input>

参考资料:

双向绑定

attrs