标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示
话不多说,先看效果图:
输入框的场景实在太多太多了,但我们偶尔也会碰到一些个性化的需求,今天给大家介绍的就是类似上面这样,可以显示标签的输入框。
先来假设一下我们的输入需求:
- 要能使用键盘输入文字
- 每次的输入可以成为独立的个体
- 每个个体使用标签的形式展现
- 输入时可以有下拉选择项
- 能对输入的内容进行校验
- 不同的校验结果有不同的类名、样式等控制
- 允许修改完成的标签内容
- 可以删除完成的标签
- 可以拖动标签进行排序换位置
- 可以在任意位置插入新标签
- 支持一次全部删除
- 支持键盘快捷键操作
- 支持自定义插槽以丰富组件定制化
从上面列出的这些来看,普通的输入框已经无法满足,需要我们去手动封装一个组件。
我们不是巨人,但是我们要站在他们的肩膀上:
QQ邮箱:跟我们的需求有很多相似的地方,我们可以借鉴一下。
vue-tags-input:一个vue组件,我们就是在它上面二次开发。
概要说明
由于vue-tags-input不能满足我们的部分需求,因此我们会增加很多自己的代码,而且它只支持vue2,我们也会扩展一份出来以支持vue3,。
我们将二开的组件命名为:vue2-tag-input和vue3-tag-input。
可以通过npm进行安装体验并使用。
为了更清晰的演示该组件的功能,将分成几个部分来一一展示。主要从这几个方面:基本输入、验证、可编辑、下拉选项、删除、快捷键、拖拽、插槽。
基本输入
<vue2-tag-input
v-model="tag"
:tags="tags">
</vue2-tag-input>
其中tag是当前输入的内容,是一个字符串,tags表示已经完成输入的内容,是一个数组,保存着每个标签的对象信息,通过示意图来看下:
那么tag的值就是"排",tags的值就是类似
[{ "text": "篮球", "tiClasses": [ "ti-valid" ],
"id": 1
},{
"text": "羽毛球",
"tiClasses": [
"ti-valid"
],
"id": 2
}]
这样形式的数组。
每当输入内容改变时,tag的值就会改变,按下回车enter键或者点击空白处即可生成一个标签,tags的值亦即发生改变。
验证
通过添加validation属性,可以对输入的内容进行校验,验证该值是否不合理,值为一个数组,表示有多个验证规则。如果满足验证,那么表示为该值不合理,会自动为生成的标签添加无效的类名(ti-invalid)。
<vue2-tag-input
v-model="tag"
:tags="tags"
:validation="validation">
</vue2-tag-input>
假设我们想要验证输入的内容是否有数字,并且是否超过了4个字,那么可以把validation的值设为这样:
[{
classes: "max-length",
rule: function({ text }) {
return /^.{4,}$/.test(text)
},
},{
classes: "no-numbers",
rule: "^([^0-9]*)$",
}]
其中rule表示要验证的规则,可以是字符串或者正则表达式或者函数,如果满足规则,则表示该值无效,那么生成标签之后将会给当前标签添加对应classes字段指定的类名,进而进一步控制元素。
会自动添加验证效果。
相应的元素也会有设定的类名。
也可以设定disableAdd字段,这样当输入的值校验为不合理时,无法生成新标签:
[{
classes: "no-numbers",
rule: "^([^0-9]*)$",
disableAdd: true
}]
可编辑
要想修改已完成的标签,使得每一项可编辑,需要添加allowEditTags属性。
<vue2-tag-input
v-model="tag"
:tags="tags"
:validation="validation"
allowEditTags>
</vue2-tag-input>
比如你想修改一个标签,那么可以单击它,这样就进入了可编辑状态,同时关闭图标变成取消图标:
之后可以按回车enter键完成修改,也可以点击取消按钮或者其他地方取消修改。
下拉选项
给组件绑定autocomplete-items属性,即可使用下拉选项功能:
<vue2-tag-input
v-model="tag"
:tags="tags"
:validation="validation"
allowEditTags
:autocomplete-items="autocompleteItems">
</vue2-tag-input>
它的值为一个数组,类似这样:
[{
text: "乒乓球",
},{
text: "保龄球",
},{
text: "桦林Disco",
}]
autocompleteItems的值也可以是动态变化的,比如通过计算属性得到,或者通过监听输入值的改变来设置。这样做的好处是可以实时过滤,已选择的项会自动从列表中隐藏。
我们举一个普通的例子,不进行过滤的:
自动弹出所有下拉选项,鼠标单击对应的项,即可添加该标签,或者使用上↑下↓键来选择,然后按回车enter键亦可。
已添加的项会自动从待选列表中隐藏。
删除
可以有两种方式进行删除已完成的标签:
- 当输入框中无值时,可以按退格键(backspace)来让标签处于待删除状态,再次按下退格键,即可删除,固定时间段内没有再次按下将会取消删除状态。
- 点击标签上面的删除图标
直接看下效果图:
快捷键
提供了多个便于操作的快捷键:
- ctrl+a:全选,可用于一次性全部删除
- 左←右→:移动光标,可用于在两个标签中间插入新标签,跟鼠标点击两个标签中间空白位置的效果一样
- ctrl+v:粘贴,用于快速添加标签,可一次生成多个,默认用分号";"分隔,可以指定separators属性修改分隔符,值为一个数组。比如我们复制这段文字:
那么粘贴到输入框中时,就会变成这样:
拖拽
如果想要更改某个标签的位置,可以通过拖拽来完成:
插槽
可以通过插槽来改变标签的展示形式或者交互行为,主要有tag-left、tag-center、tag-right、tag-actions、between-elements、autocomplete-header、autocomplete-item、autocomplete-footer。
这里我们只介绍一个,来看下它们的使用方式以及发生的作用。
tag-left:标签内容的左置区域,比如我们要在内容的前面加上序号
<vue2-tag-input
v-model="tag"
:tags="tags">
<div
slot="tag-left"
slot-scope="props"
>
{{ props.index + 1 }}
</div>
</vue2-tag-input>
看下效果:
其他插槽同理,比如传入tag-actions来更改操作区的图标。
其他
最后来一个样式自定义的案例:
// template
<div class="tag-input-box">
请输入您想要的内容:<br /><br />
<vue2-tag-input
v-model="tag"
:tags="tags"
:validation="validation">
</vue2-tag-input>
</div>
// js
tag: "",
tags: [],
validation: [{
classes: "no-numbers",
rule: "^([^0-9]*)$"
}]
.tag-input-box >>> .ti-new-tag-input {background: transparent;color: #b7c4c9;}
.tag-input-box >>> .ti-input {padding: 4px 10px;transition: border-bottom 200ms ease;}
.tag-input-box >>> .vue-tags-input.ti-focus .ti-input {border: 1px solid #ebde6e;}
.tag-input-box >>> .ti-tag {position: relative;background: #ebde6e;color: #283944;}
.tag-input-box >>> .ti-tag.ti-invalid {background-color: #e88a74;}
.tag-input-box >>> .ti-new-tag-input.ti-invalid {color: #e88a74;}
.tag-input-box >>> .ti-tag:after {transition: transform 0.2s;position: absolute;content: "";height: 2px;width: 102%;left: -1%;top: calc(50% - 1px);background-color: #000;transform: scaleX(0);}
.tag-input-box >>> .ti-deletion-mark:after {transform: scaleX(1);}
可以任意的定制输入框和标签以及下拉选项的样式和交互。
最后
还有很多可配置的属性和事件,这里就不一一全部介绍了,比如是否允许输入同样的值、设置最大标签数、是否禁用、删除事件可以阻止删除操作、添加事件可以修改添加内容或阻止添加等等等等。
目前有vue2和vue3两个版本,都是基于JohMun的vue-tags-input改造的,看你能不能玩出花来!
转载自:https://juejin.cn/post/7236262749433479228