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 相关文章推荐
一个JavaScript继承的实现
Oct 24 Javascript
ExtJs 表单提交登陆实现代码
Aug 19 Javascript
jQuery学习笔记之jQuery的事件
Dec 22 Javascript
JS的get和set使用示例
Feb 20 Javascript
javascript cookie的简单应用
Feb 24 Javascript
JavaScript 实现的checkbox经典实例分享
Oct 16 Javascript
任意Json转成无序列表的方法示例
Dec 09 Javascript
ES6扩展运算符用法实例分析
Oct 31 Javascript
npm的lock机制解析
Jun 20 Javascript
使用VUE实现在table中文字信息超过5个隐藏鼠标移到时弹窗显示全部
Sep 16 Javascript
微信小程序实现轨迹回放的示例代码
Dec 13 Javascript
Vue数组响应式操作及高阶函数使用代码详解
Aug 01 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使用百度天气接口示例
2014/04/22 PHP
php数组转成json格式的方法
2015/03/09 PHP
超级酷和最实用的jQuery实例收集(20个)
2010/04/21 Javascript
js实现无需数据库的县级以上联动行政区域下拉控件
2013/08/14 Javascript
js兼容的placeholder属性详解
2013/08/18 Javascript
JavaScript设计模式之工厂模式和构造器模式
2015/02/11 Javascript
jquery实现手机号码选号的方法
2015/07/31 Javascript
使用Node.js处理前端代码文件的编码问题
2016/02/16 Javascript
最全的Javascript编码规范(推荐)
2016/06/22 Javascript
MUI 上拉刷新/下拉加载功能实例代码
2017/04/13 Javascript
纯js实现的积木(div层)拖动功能示例
2017/07/19 Javascript
详谈commonjs模块与es6模块的区别
2017/10/18 Javascript
微信小程序实现鼠标拖动效果示例
2017/12/01 Javascript
(模仿京东用户注册)用JQuery实现简单表单验证,初学者必看
2018/01/08 jQuery
jQuery中的for循环var与let的区别
2018/04/21 jQuery
纯JS实现出生日期[年月日]下拉菜单效果
2018/06/01 Javascript
原生JavaScript实现remove()和recover()功能示例
2018/07/24 Javascript
从0到1搭建element后台框架优化篇(打包优化)
2019/05/12 Javascript
微信小程序停止其他视频播放当前视频的实例代码
2019/12/25 Javascript
在Angular项目使用socket.io实现通信的方法
2021/01/05 Javascript
详解Python的Django框架中的中间件
2015/07/24 Python
对python多线程SSH登录并发脚本详解
2019/02/14 Python
Python、 Pycharm、Django安装详细教程(图文)
2019/04/12 Python
Python画图高斯分布的示例
2019/07/10 Python
Django框架反向解析操作详解
2019/11/28 Python
HTML5样式控制示例代码
2013/11/27 HTML / CSS
英国健身超市:Fitness Superstore
2019/06/17 全球购物
美国眼镜网站:LensCrafters
2020/01/19 全球购物
do you have any Best Practice for testing
2016/06/04 面试题
JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
2013/07/02 面试题
高中生职业规划范文
2014/03/09 职场文书
小学二年级学生评语
2014/04/21 职场文书
避暑山庄导游词
2015/02/04 职场文书
奖励通知
2015/04/22 职场文书
Mysql分析设计表主键为何不用uuid
2022/03/31 MySQL
Centos系统通过Docker安装并搭建MongoDB数据库
2022/04/12 MongoDB