likes
comments
collection
share

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

作者站长头像
站长
· 阅读数 20

话不多说,先看效果图:

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

输入框的场景实在太多太多了,但我们偶尔也会碰到一些个性化的需求,今天给大家介绍的就是类似上面这样,可以显示标签的输入框。

先来假设一下我们的输入需求:

  1. 要能使用键盘输入文字
  2. 每次的输入可以成为独立的个体
  3. 每个个体使用标签的形式展现
  4. 输入时可以有下拉选择项
  5. 能对输入的内容进行校验
  6. 不同的校验结果有不同的类名、样式等控制
  7. 允许修改完成的标签内容
  8. 可以删除完成的标签
  9. 可以拖动标签进行排序换位置
  10. 可以在任意位置插入新标签
  11. 支持一次全部删除
  12. 支持键盘快捷键操作
  13. 支持自定义插槽以丰富组件定制化

从上面列出的这些来看,普通的输入框已经无法满足,需要我们去手动封装一个组件。

我们不是巨人,但是我们要站在他们的肩膀上:

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-input:仿QQ邮箱来增强你的组件交互与界面展示

那么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字段指定的类名,进而进一步控制元素。

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

会自动添加验证效果。

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

相应的元素也会有设定的类名。

也可以设定disableAdd字段,这样当输入的值校验为不合理时,无法生成新标签:

[{
  classes: "no-numbers",
    rule: "^([^0-9]*)$",
      disableAdd: true
}]

可编辑

要想修改已完成的标签,使得每一项可编辑,需要添加allowEditTags属性。

<vue2-tag-input
  v-model="tag"
  :tags="tags"
  :validation="validation"
  allowEditTags>
</vue2-tag-input>

比如你想修改一个标签,那么可以单击它,这样就进入了可编辑状态,同时关闭图标变成取消图标:

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

之后可以按回车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的值也可以是动态变化的,比如通过计算属性得到,或者通过监听输入值的改变来设置。这样做的好处是可以实时过滤,已选择的项会自动从列表中隐藏。

我们举一个普通的例子,不进行过滤的:

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

自动弹出所有下拉选项,鼠标单击对应的项,即可添加该标签,或者使用上↑下↓键来选择,然后按回车enter键亦可。

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

已添加的项会自动从待选列表中隐藏。

删除

可以有两种方式进行删除已完成的标签:

  1. 当输入框中无值时,可以按退格键(backspace)来让标签处于待删除状态,再次按下退格键,即可删除,固定时间段内没有再次按下将会取消删除状态。
  2. 点击标签上面的删除图标

直接看下效果图:

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

快捷键

提供了多个便于操作的快捷键:

  1. ctrl+a:全选,可用于一次性全部删除

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

  1. 左←右→:移动光标,可用于在两个标签中间插入新标签,跟鼠标点击两个标签中间空白位置的效果一样

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

  1. ctrl+v:粘贴,用于快速添加标签,可一次生成多个,默认用分号";"分隔,可以指定separators属性修改分隔符,值为一个数组。比如我们复制这段文字:

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

那么粘贴到输入框中时,就会变成这样:

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

拖拽

如果想要更改某个标签的位置,可以通过拖拽来完成:

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

插槽

可以通过插槽来改变标签的展示形式或者交互行为,主要有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-input:仿QQ邮箱来增强你的组件交互与界面展示

其他插槽同理,比如传入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);}

标签输入框tag-input:仿QQ邮箱来增强你的组件交互与界面展示

可以任意的定制输入框和标签以及下拉选项的样式和交互。

最后

还有很多可配置的属性和事件,这里就不一一全部介绍了,比如是否允许输入同样的值、设置最大标签数、是否禁用、删除事件可以阻止删除操作、添加事件可以修改添加内容或阻止添加等等等等。

目前有vue2和vue3两个版本,都是基于JohMun的vue-tags-input改造的,看你能不能玩出花来!

转载自:https://juejin.cn/post/7236262749433479228
评论
请登录