vue组件系列之TagsInput详解


Posted in Javascript onMay 14, 2020

简介

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

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

vue组件系列之TagsInput详解

注:以下代码需要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的文章就介绍到这了,更多相关vue组件TagsInput内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
jquery png 透明解决方案(推荐)
Aug 21 Javascript
原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)
Jun 21 Javascript
js实现适配不同的屏幕大小
Apr 10 Javascript
xmlplus组件设计系列之文本框(TextBox)(3)
May 03 Javascript
JavaScript算法教程之sku(库存量单位)详解
Jun 29 Javascript
详解Vue2中组件间通信的解决全方案
Jul 28 Javascript
微信小程序 获取session_key和openid的实例
Aug 17 Javascript
详解Vue用cmd创建项目
Feb 12 Javascript
Angular中使用ng-zorro图标库部分图标不能正常显示问题
Apr 22 Javascript
JS实现的字符串数组去重功能小结
Jun 17 Javascript
微信小程序npm引入vant-weapp的踩坑记录
Aug 01 Javascript
JavaScript实现拖拽和缩放效果
Aug 24 Javascript
ant-design-vue按需加载的坑的解决
May 14 #Javascript
JavaScript数组排序功能简单实现
May 14 #Javascript
Typescript3.9 常用新特性一览(推荐)
May 14 #Javascript
Node.js API详解之 Error模块用法实例分析
May 14 #Javascript
微信小程序 获取手机号 JavaScript解密示例代码详解
May 14 #Javascript
JavaScript, select标签元素左右移动功能实现
May 14 #Javascript
vue实现商品列表的添加删除实例讲解
May 14 #Javascript
You might like
PHP利用func_get_args和func_num_args函数实现函数重载实例
2014/11/12 PHP
PHP使用数组依次替换字符串中匹配项
2016/01/08 PHP
php支付宝APP支付功能
2020/07/29 PHP
基于OO的动画附加插件,可以实现弹跳、渐隐等动画效果 分享
2013/06/24 Javascript
js渐变显示渐变消失示例代码
2013/08/01 Javascript
javascript实现在指定元素中垂直水平居中
2015/09/13 Javascript
JS实现适合于后台使用的动画折叠菜单效果
2015/09/21 Javascript
基于JavaScript实现鼠标悬浮弹出跟随鼠标移动的带箭头的信息层
2016/01/18 Javascript
JQuery validate插件Remote用法大全
2016/05/15 Javascript
逻辑表达式中与或非的用法详解
2016/06/06 Javascript
Vue原理剖析 实现双向绑定MVVM
2017/05/03 Javascript
vue组件父子间通信详解(三)
2017/11/07 Javascript
值得收藏的vuejs安装教程
2017/11/21 Javascript
详解vue-cli 快速搭建单页应用之遇到的问题及解决办法
2018/03/01 Javascript
理顺8个版本vue的区别(小结)
2018/09/17 Javascript
JavaScript Math对象和调试程序的方法分析
2019/05/13 Javascript
js中forEach,for in,for of循环的用法示例小结
2020/03/14 Javascript
vue动态设置页面title的方法实例
2020/08/23 Javascript
Vue ​v-model相关知识总结
2021/01/28 Vue.js
[01:05:12]2014 DOTA2国际邀请赛中国区预选赛 TongFu VS CIS-GAME
2014/05/21 DOTA
[02:09]EHOME夺得首届辉夜杯冠军—现场颁奖仪式
2015/12/28 DOTA
[43:51]2018DOTA2亚洲邀请赛3月30日 小组赛B组 EG VS Secret
2018/03/31 DOTA
跟老齐学Python之编写类之一创建实例
2014/10/11 Python
Python读csv文件去掉一列后再写入新的文件实例
2017/12/28 Python
python随机在一张图像上截取任意大小图片的方法
2019/01/24 Python
python tkinter canvas 显示图片的示例
2019/06/13 Python
在python中用print()输出多个格式化参数的方法
2019/07/16 Python
Django框架HttpRequest对象用法实例分析
2019/11/01 Python
pycharm 设置项目的根目录教程
2020/02/12 Python
使用Keras画神经网络准确性图教程
2020/06/15 Python
Jmeter HTTPS接口测试证书导入过程图解
2020/07/22 Python
纯CSS3实现绘制各种图形实现代码详细整理
2012/12/26 HTML / CSS
欧洲最大的美妆零售网站:Feelunique
2017/01/14 全球购物
优质服务活动实施方案
2014/05/02 职场文书
创业计划书之校园超市
2019/09/12 职场文书
python处理json数据文件
2022/04/11 Python