Input 组件通常是一个组件库的基础,不少组件都须要依赖它,因此该组件的特色在于:基于原生的 HTML 标签进行拓展的 Input 组件。html
this.$slots
拓展 slot
,便于二次封装;v-model
与 v-on=$listeners
的相关处理;代码git
<!-- 基础用法 -->
<fat-input placeholder="请输入内容" v-model="inputValue" />
<!-- 复合型输入框 -->
<fat-input placeholder="请输入内容">
<template slot="prepend">
<div class="prepend-part c-size-s">Http://</div>
</template>
<template slot="append">
<div class="append-part c-size-s">.com</div>
</template>
</fat-input>
复制代码
实例地址:Input 实例github
代码地址:Github UI-Librarybash
首先拓展 type
属性,添加值为 textarea
的状态,设计该组件的结构为 input
以下app
<div :class="['input-wrapper']">
<textarea
v-if="type === 'textarea'"
class="textarea-inner"
/>
<template v-else>
<input
:class="['input-inner']"
:type="type"
/>
</template>
</div>
复制代码
基础功能实现:ui
添加 v-bind="$attrs"
指令,来实现原生 input
的相关属性,例如 placeholder
、readonly
、maxlength
等,在 input
以及 textarea
上,该指令可以在组件上绑定父做用域中不做为 prop 被识别 (且获取) 的特性 (class 和 style 除外);this
添加 v-on="$listeners"
指令,实现组件上的 change
、focus
、blur
事件,因为 Input 组件须要支持 v-model="inputValue"
,而在 input
标签 上 v-model
依赖 input
事件, 其原理是spa
event => this.$emit("input", event.target.value)
复制代码
可是直接使用时,$emit("input", arg)
中 arg
是一个 [object InputEvent]
,与实际应用状况不服, 二者会报异常,这时利用 computed 属性对 $listeners
进行修改设计
export default {
model: {
prop: "value",
event: "input"
},
computed: {
inputListeners() {
return Object.assign({}, this.$listeners, {
input: event => this.$emit("input", event.target.value)
});
}
}
};
复制代码
而后再利用 v-on="inputListeners"
绑定到组件上,同时 watch value
,code
watch: {
value: {
handler(newVal) {
this.inputValue = newVal;
},
// 添加immediate,减小created生命周期中的赋值
immediate: true
}
}
复制代码
样式拓展实现:
textarea
时生效),添加<fat-icon v-if="prefixIcon" class="icon" :name="prefixIcon"/>
<input
:class="['input-inner']"
:type="type"
:value="inputValue"
v-bind="$attrs"
v-on="inputListeners"
/>
<fat-icon v-if="suffixIcon" class="icon" :name="suffixIcon"/>
复制代码
<slot name="prepend"></slot>
<input
:class="['input-inner', { 'have-prepand': havePrepand, 'have-append': haveAppend }]"
:type="type"
:value="inputValue"
v-bind="$attrs"
v-on="inputListeners"
/>
<slot name="append"></slot>
复制代码
而且为了兼容样式,须要对 input-inner
添加两个类,have-prepand
以及 have-append
,它们的状态主要是检查 this.$slots
对象computed: {
havePrepand() {
return this.$slots.prepend;
},
haveAppend() {
return this.$slots.append;
}
}
复制代码
因为上述实现过程,都是在原生的 Input
组件进行的拓展,在实际应用时,可结合业务进行封装以及抽象。 使用时,主要注意点两个具名插槽的使用。
<div class="demo-row-content">
<fat-input placeholder="请输入内容"> <template slot="prepend"> <div class="prepend-part c-size-s">Http://</div> </template> <template slot="append"> <div class="append-part c-size-s">.com</div> </template> </fat-input> </div>
复制代码
原创声明: 该文章为原创文章,转载请注明出处。