简介

TagsInput 是一种可编辑的输入框,通过回车或者分号来分割每个标签,用回退键删除上一个标签。用 vue 来实现还是比较简单的。

先看效果图,下面会一步一步实现他。

  • 注:以下代码需要vue-cli环境才能执行

(一)伪造一个输入框

因为单行的文本框只能展示纯文本,所以图里面的标签实际上都是 html元素,用vue模板来写的话,是这样的:

<template>
<div class="muli-tags" @click='focus'>
<button class='btn' v-for='(tag, index) in tags' :key='index'>
{{tag}}
</button>
<input type="text" ref='input' v-model='current'>
</div>
</template> <script>
export default {
name: 'TagsInput',
methods: {
focus () {
this.$refs.input.focus()
},
},
data () {
return {
tags: [],
current: ''
}
}
}
</script> <style lang='less'>
.muli-tags{
padding: 5px 10px;
display: block;
border: 1px solid #ccc;
input{
background: transparent;
}
}
.btn{
margin: 0 5px 3px 0;
padding: 4px 5px;
background: #fff;
border: 1px solid #eee;
box-shadow: 0 0 4px;
}
</style>

(二)监听输入

在伪造好一个输入框之后,我们对输入框的事件进行处理,

  • 回车和逗号会把input的值添加到tags数组,然后清空input
  • 添加值之前,判断tags数组是否已经包含同名的值
  • 按回退键,删除最近的一个标签
// @keydown.188   188代表是是分号键的keyCode
<input type="text"
ref='input'
@keyup.enter="add"
@keydown.delete="del"
@keydown.188='split'
v-model='current'> methods: {
// 按下分号键的时候,需要阻止默认事件,否则会出现分号
split (e) {
e.preventDefault()
this.add(e)
},
add (e) {
const val = e.target.value
if (!val) return
// 如果已经存在相同tag,不再添加
if (this.tags.indexOf(val) > -1) return
// 把输入值添加到tag,并清空文本框
this.tags.push(val)
this.current = ''
},
del (e) {
// 当文本框内没有值,再按回退键,则删除最后一个tag
if (!e.target.value.length) {
this.tags.pop()
}
},
}

(三)删除标签

前面都是通过键盘来操作标签,鼠标点击标签应该也是可以删除的

<button class='btn' v-for='(tag, index) in tags' :key='index' @click='delTag(index)'>{{tag}} <span>x</span></button>

methods: {
// 删除点击的标签
delTag (index) {
this.tags.splice(index, 1)
}
}

(四)自定义 v-model

通过上面的步骤,一个 tagsinput 组件就已经做好了,再给他添加自定义的 v-model ,让他可以像input一样响应表单数据。

  // props
props: {
value: Array,
required: true,
default: () => []
} // computed
computed: {
tags () {
return this.value.slice()
}
} // methods
methods: {
// 删除点击的标签
delTag (index) {
this.tags.splice(index, 1)
this.$emit('input', this.tags)
}
}

(五)完整代码

// TagsInput.vue
<template>
<div class="muli-tags" @click='focus'>
<button class='btn' v-for='(tag, index) in tags' :key='index' @click='delTag(index)'>{{tag}} <span>x</span></button>
<input type="text"
ref='input'
@keyup.enter="add"
@keydown.delete="del"
@keydown.188='split'
v-model='current'>
</div>
</template> <script>
export default {
props: {
value: Array,
required: true,
default: () => []
},
methods: {
focus () {
this.$refs.input.focus()
},
split (e) {
e.preventDefault()
this.add(e)
},
add (e) {
const val = e.target.value
if (!val) return
if (this.tags.indexOf(val) > -1) return
this.tags.push(val)
this.$emit('input', this.tags)
this.current = ''
},
del (e) {
if (!e.target.value.length) {
this.tags.pop()
this.$emit('input', this.tags)
}
},
delTag (index) {
this.tags.splice(index, 1)
this.$emit('input', this.tags)
}
},
computed: {
tags () {
return this.value.slice()
}
},
data () {
return {
current: ''
}
}
}
</script> <style lang='less'>
.muli-tags{
padding: 5px 10px;
display: block;
border: 1px solid #ccc;
input{
background: transparent;
}
.btn{
margin: 0 5px 3px 0;
padding: 4px 5px;
background: #fff;
border: 1px solid #eee;
box-shadow: 0 0 4px;
}
}
</style>

作为组件被调用,这样就可以看到像文章开头那幅图一样的组件了。

// 父组件
<template>
<tags-input v-model='tags'/>
</template>
<script>
import TagsInput from './TagsInput.vue'
export default {
components: {
TagsInput
},
data () {
return {
tags: ['tag1', 'tag2', 'tag3']
}
}
}
</script>

vue组件--TagsInput的更多相关文章

  1. vue组件

    分享出来让思路更成熟. 首先组件是 Vue.js 最强大的功能之一. 可以减少很多的工作量,提高工作效率. 编写一个可复用性的组件,虽然官网上也有.... 编写可复用性的vue组件 具备一下的几个要求 ...

  2. vue组件的配置属性

    vue组件的声明语法: Vue.component('component-name',{ template:'<p>段落{{prop1}} {{prop2}}</p>', da ...

  3. vue组件,撸第一个

    实现此例您可以学到: vue-cli的基本应用 父组件如何向子组件传递值 单文件组件如何引入scss v-on和v-for的基础应用 源码下载 一.搭建vue开发环境 更换镜像到cnpmnpm ins ...

  4. vue组件最佳实践

    看了老外的一篇关于组件开发的建议(强烈建议阅读英文原版),感觉不错翻译一下加深理解. 这篇文章制定一个统一的规则来开发你的vue程序,以至于达到一下目的. 1.让开发者和开发团队更容易发现一些事情. ...

  5. JS组件系列——又一款MVVM组件:Vue(二:构建自己的Vue组件)

    前言:转眼距离上篇 JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查) 已有好几个月了,今天打算将它捡起来,发现好久不用,Vue相关技术点都生疏不少.经过这几个月的时间,Vue ...

  6. vue组件大集合 component

    vue组件分为全局组件.局部组件和父子组件,其中局部组件只能在el定义的范围内使用, 全局组件可以在随意地方使用,父子组件之间的传值问题等. Vue.extend 创建一个组件构造器 template ...

  7. 【Vue】详解Vue组件系统

    Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根节点这一初始化操作上: new Vue({ el: '#app' }) 注册组件并使用—— 全局注册 通过Vue.comp ...

  8. 关于vue组件的一个小结

    用vue进行开发到目前为止也有将近一年的时间了,在项目技术选型的时候隔壁组选 react的时候我们坚持使用vue作为前端的开发框架.虽然两者思想上的差异不大,但是vue的语法在代码的可读性以及后期的维 ...

  9. Vue组件基础用法

    前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需, ...

随机推荐

  1. js 获取后缀参数

    function getQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&] ...

  2. rimraf命令 递归删除目录所有文件

    使用webpack build文件项目时每次都会生成一个dist目录,有时需要把dist目录里的所以旧文件全部删掉, 除了可以使用rm -rf /dist/命令删除外,还可以使用rimraf /dis ...

  3. tyvj1953 Normal

    题目链接 正解:点分治+$FFT$. 很想吐槽一下$bzoj$,为什么搬了别的$oj$的题还设成权限题.. 首先我们考虑期望的线性性,即考虑每个点的贡献. 显然每个点的贡献就是它在点分树上的深度,所以 ...

  4. cascade rcnn论文总结

    1.bouding box regression总结: rcnn使用l2-loss 首先明确l2-loss的计算规则: L∗=(f∗(P)−G∗)2,∗代表x,y,w,h    整个loss : L= ...

  5. Java静态代理学习

    代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式一般涉及 ...

  6. 百度api:根据经纬度获取地理位置信息

    调用百度api,根据经度和纬度获取地理位置信息,返回Json. C#代码: using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Syste ...

  7. HDU 2602 Bone Collector(经典01背包问题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2602 Bone Collector Time Limit: 2000/1000 MS (Java/O ...

  8. iOS蓝牙APP常驻后台

    iOS蓝牙类APP常驻后台的实现方法,经过在苹果开发者论坛询问,以及查看苹果开发者文档,最后得出正确的方法为: 1.设置plist,蓝牙权限 2.到target-capabilities-backgr ...

  9. [修正] Firemonkey Windows & macOS 平台下 Edit & Memo 中文输入后会取消原选取文字的 BUG

    问题:Firemonkey Windows & macOS 平台下 Edit & Memo 中文输入后会取消原选取文字的 BUG 适用版本:Delphi 10.1.2 & 10 ...

  10. sqli-labs学习(less-1-less-4)

    学习sqli-labs之前先介绍一些函数,以便于下面的payload看的懂 group_concat函数 将查询出来的多个结果连接成一个字符串结果,用于在一个回显显示多个结果 同理的还有 concat ...