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实现网页跳转或用命令打开指定网页的解决方法
Jul 09 Javascript
js单例模式详解实例
Nov 21 Javascript
使用GruntJS构建Web程序之构建篇
Jun 04 Javascript
Javascript 实现图片无缝滚动
Dec 19 Javascript
JavaScript DOM进阶方法
Apr 13 Javascript
JS实现点击事件统计的简单实例
Jul 10 Javascript
微信小程序 Canvas增强组件实例详解及源码分享
Jan 04 Javascript
vue loadmore 组件滑动加载更多源码解析
Jul 19 Javascript
基于Vue单文件组件详解
Sep 15 Javascript
Easyui 去除jquery-easui tab页div自带滚动条的方法
May 10 jQuery
详解基于 Node.js 的轻量级云函数功能实现
Jul 08 Javascript
js实现轮播图效果 纯js实现图片自动切换
Aug 09 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之sphinx
2013/05/15 PHP
php实现将数组转换为XML的方法
2015/03/09 PHP
Laravel5.1数据库连接、创建数据库、创建model及创建控制器的方法
2016/03/29 PHP
php爬取天猫和淘宝商品数据
2018/02/23 PHP
取得一定长度的内容,处理中文
2006/12/20 Javascript
jquery CSS选择器笔记
2010/03/29 Javascript
jquery ui对话框实例代码
2013/05/10 Javascript
js 控制页面跳转的5种方法
2013/09/09 Javascript
javascript 获取iframe里页面中元素值的方法
2014/02/17 Javascript
浅谈JavaScript的push(),pop(),concat()方法
2016/06/03 Javascript
在线引用最新jquery文件的实现方法
2016/08/26 Javascript
原生JS:Date对象全面解析
2016/09/06 Javascript
Bootstrap3 内联单选和多选框
2016/12/29 Javascript
浅谈JS封闭函数、闭包、内置对象
2017/07/18 Javascript
node+koa2+mysql+bootstrap搭建一个前端论坛
2018/05/06 Javascript
Vue中的字符串模板的使用
2018/05/17 Javascript
React中如何引入Angular组件详解
2018/08/09 Javascript
Vue 莹石摄像头直播视频实例代码
2018/08/31 Javascript
JQuery的加载和选择器用法简单示例
2019/05/13 jQuery
解决三元运算符 报错“SyntaxError: can''t assign to conditional expression”
2020/02/12 Javascript
video.js添加自定义组件的方法
2020/12/09 Javascript
Python版的文曲星猜数字游戏代码
2013/09/02 Python
Python subprocess模块功能与常见用法实例详解
2018/06/28 Python
python实现感知器算法(批处理)
2019/01/18 Python
Python 画出来六维图
2019/07/26 Python
python3实现的zip格式压缩文件夹操作示例
2019/08/17 Python
Django 权限管理(permissions)与用户组(group)详解
2020/11/30 Python
Sandro Paris美国官网:典雅别致的法国时尚服饰品牌
2017/12/26 全球购物
捷克家电和家具购物网站:OKAY.cz
2020/07/23 全球购物
Linux中如何用命令创建目录
2015/01/12 面试题
室内设计实习自我鉴定
2013/09/25 职场文书
中国梦演讲稿3分钟
2014/08/19 职场文书
2014年护士个人工作总结
2014/11/11 职场文书
文化苦旅读书笔记
2015/06/29 职场文书
详解如何使用Node.js实现热重载页面
2021/05/06 Javascript
关于Python中进度条的六个实用技巧分享
2022/04/05 Python