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+EasyDrag 实现弹出可拖动的Div,同时向Div传值,然后返回Div选中的值
Oct 24 Javascript
getElementsByTagName vs selectNodes效率 及兼容的selectNodes实现
Feb 26 Javascript
javascript预览上传图片发现的问题的解决方法
Nov 25 Javascript
javascript实现的平方米、亩、公顷单位换算小程序
Aug 11 Javascript
如何在MVC应用程序中使用Jquery
Nov 17 Javascript
AngularJS过滤器filter用法总结
Dec 13 Javascript
微信小程序 出现47001 data format error原因解决办法
Mar 10 Javascript
jquery中封装函数传递当前元素的方法示例
May 05 jQuery
微信小程序 新建登录页并实现tabBar隐藏
Jun 13 Javascript
微信小程序使用scroll-view标签实现自动滑动到底部功能的实例代码
Nov 09 Javascript
详解Vue中组件的缓存
Apr 20 Javascript
DatePickerDialog 自定义样式及使用全解
Jul 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
phpexcel导出excel的颜色和网页中的颜色显示不一致
2012/12/11 PHP
PHP文件上传主要代码讲解
2013/09/30 PHP
PHP连接MySQL的2种方法小结以及防止乱码
2014/03/11 PHP
WordPress中制作导航菜单的PHP核心方法讲解
2015/12/11 PHP
如何打开php的gd2库
2017/02/09 PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
2017/11/17 PHP
FCK调用方法..
2006/12/21 Javascript
IE8 浏览器Cookie的处理
2009/01/31 Javascript
判断脚本加载是否完成的方法
2009/05/26 Javascript
jQuery获取节点和子节点文本的方法
2014/07/22 Javascript
Javascript控制input输入时间格式的方法
2015/01/28 Javascript
解决Jquery向页面append新元素之后事件的绑定问题
2015/03/16 Javascript
Jquery实现仿京东商城省市联动菜单
2015/11/19 Javascript
Javascript Function.prototype.bind详细分析
2016/12/29 Javascript
详解JavaScript中this的指向问题
2017/01/20 Javascript
80%应聘者都不及格的JS面试题
2017/03/21 Javascript
Angular获取手机验证码实现移动端登录注册功能
2017/05/17 Javascript
原生JS实现简单的无缝自动轮播效果
2018/09/26 Javascript
小程序接口的promise化的实现方法
2019/12/11 Javascript
详细分析vue响应式原理
2020/06/22 Javascript
如何实现echarts markline标签名显示自己想要的
2020/07/20 Javascript
Vue-router编程式导航的两种实现代码
2021/03/04 Vue.js
python urllib爬取百度云连接的实例代码
2017/06/19 Python
python-tkinter之按钮的使用,开关方法
2019/06/11 Python
python获取磁盘号下盘符步骤详解
2019/06/19 Python
详解python和matlab的优势与区别
2019/06/28 Python
解决pycharm最左侧Tool Buttons显示不全的问题
2019/12/17 Python
Python Http请求json解析库用法解析
2020/11/28 Python
详解Python遍历列表时删除元素的正确做法
2021/01/07 Python
Python爬虫入门教程01之爬取豆瓣Top电影
2021/01/24 Python
英国最大的奢侈珠宝和手表网站:C W Sellors
2017/02/10 全球购物
我的珠宝盒:Ma boîte à bijoux
2019/08/27 全球购物
体育教师工作总结的自我评价
2013/10/10 职场文书
成语的广告词
2014/03/19 职场文书
2014年百日安全生产活动总结
2014/05/04 职场文书
利用Python第三方库实现预测NBA比赛结果
2021/06/21 Python