el-input是element ui中使用最频繁的组件之一了,分析其构成从四个方面入手:DOM结构,属性,样式,事件入手
DOM结构:
<div>
<input />
</div>
结构很简单,这就相当于一个主干,剩下的样式,事件,属性都在这个基础上扩充
属性:
既然是封装,input原生的属性基本上都要覆盖到,个人猜测element团队是按照w3c官方资料来整理的,这样绝对保证不遗漏,这种方式很值得借鉴,如下:
// 兼容文本框和文本域的情况
<template v-if="type !== 'textarea'">
// code..
</template>
<textarea v-else>
// code..
</textarea>
// 兼容了tabindex属性,文本框,密码框,是否禁用,是否自动完成,是否只读,input,focus,blur,change事件
<input
:tabindex="tabindex"
v-if="type !== 'textarea'"
class="el-input__inner"
v-bind="$attrs"
:type="showPassword ? (passwordVisible ? 'text': 'password') : type"
:disabled="inputDisabled"
:readonly="readonly"
:autocomplete="autoComplete || autocomplete"
ref="input"
@compositionstart="handleCompositionStart"
@compositionend="handleCompositionEnd"
@input="handleInput"
@focus="handleFocus"
@blur="handleBlur"
@change="handleChange"
:aria-label="label"
>
这些属性都通过父组件的props方式传给子组件
样式:
样式控制比较简单,根据props属性,结合数组和对象方式,拼凑出符合实际要求的样式组。从源码可以看出样式主要应用在input父元素div上以及前置元素和后置元素span上
// 根据type确定应用el-textarea还是el-input
// 根据inputDisabled属性确定是否启用is-disabled属性,其他类推
// 同时添加了鼠标移入移出时的hover样式控制
<div :class="[
type === 'textarea' ? 'el-textarea' : 'el-input',
inputSize ? 'el-input--' + inputSize : '',
{
'is-disabled': inputDisabled,
'el-input-group': $slots.prepend || $slots.append,
'el-input-group--append': $slots.append,
'el-input-group--prepend': $slots.prepend,
'el-input--prefix': $slots.prefix || prefixIcon,
'el-input--suffix': $slots.suffix || suffixIcon || clearable || showPassword
}
]"
@mouseenter="hovering = true"
@mouseleave="hovering = false"
>
// code...
</div>
事件:
组件除提供focus,blur,change等常见事件外,还提供了很多可通过配置项启用的事件,如:
clearable // 配置项,设置true后显示叉号,点击直接清除input框内容
总结:
el-input实现的功能还是挺多的,总体思路就按上面进行,尽可能通过各种配置项简化使用,内部实现则是功能最小化,就知识层面来说没什么难度,关键胜在结构严谨缜密,相信很多人都能看的懂,但要自己写一个就没那么容易了。