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中令你抓狂的魔术变量
Nov 30 Javascript
qTip2 精致的基于jQuery提示信息插件
Feb 17 Javascript
Javascript学习笔记之函数篇(五) : 构造函数
Nov 23 Javascript
常用的js方法合集
Mar 10 Javascript
javascript 玩转Date对象(实例讲解)
Jul 11 Javascript
实用的Vue开发技巧
May 30 Javascript
JS实现前端动态分页码代码实例
Jun 02 Javascript
vue data变量相互赋值后被实时同步的解决步骤
Aug 05 Javascript
JavaScript中ES6规范中let和const的用法和区别
Aug 06 Javascript
Openlayers实现扩散的动态点(水纹效果)
Aug 17 Javascript
js代码编写无缝轮播图
Sep 13 Javascript
基于openlayers实现角度测量功能
Sep 28 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格式化工具Beautify PHP小小BUG
2008/04/24 PHP
关于更改Zend Studio/Eclipse代码风格主题的介绍
2013/06/23 PHP
PHP基本语法总结
2014/09/06 PHP
在html文件中也可以执行php语句的方法
2015/04/09 PHP
HTML 自动伸缩的表格Table js实现
2009/04/01 Javascript
前端开发部分总结[兼容性、DOM操作、跨域等](持续更新)
2010/03/04 Javascript
分享8款优秀的 jQuery 加载动画和进度条插件
2012/10/24 Javascript
js获取url参数值的两种方式
2013/09/10 Javascript
js 中的switch表达式使用示例
2020/06/03 Javascript
JQuery显示隐藏页面元素的方法总结
2015/04/16 Javascript
jQuery实现鼠标悬停背景翻转的黑色导航菜单代码
2015/09/14 Javascript
快速掌握Node.js事件驱动模型
2016/03/21 Javascript
纯JS焦点图特效实例(可一个页面多用)
2016/12/07 Javascript
AngularJS 限定$scope的范围实例详解
2017/06/23 Javascript
JavaScript创建对象_动力节点Java学院整理
2017/06/27 Javascript
vue component组件使用方法详解
2017/07/14 Javascript
JavaScript 值类型和引用类型的初次研究(推荐)
2017/07/19 Javascript
three.js中文文档学习之如何本地运行详解
2017/11/20 Javascript
nodejs中实现用户注册路由功能
2019/05/20 NodeJs
Electron vue的使用教程图文详解
2019/07/05 Javascript
JavaScript数组去重实现方法小结
2020/01/17 Javascript
python检测某个变量是否有定义的方法
2015/05/20 Python
在Django中管理Users和Permissions以及Groups的方法
2015/07/23 Python
Python编程实战之Oracle数据库操作示例
2017/06/21 Python
下载python中Crypto库报错:ModuleNotFoundError: No module named ‘Crypto’的解决
2018/04/23 Python
浅谈python3打包与拆包在函数的应用详解
2020/05/02 Python
python为什么会环境变量设置不成功
2020/06/23 Python
numpy中生成随机数的几种常用函数(小结)
2020/08/18 Python
CSS3的文字阴影—text-shadow的使用方法
2012/12/25 HTML / CSS
Lululemon加拿大官网:加拿大知名体育服装零售商
2019/04/12 全球购物
怀念母亲教学反思
2014/04/28 职场文书
化学专业自荐信
2014/05/28 职场文书
中专毕业生的自荐书
2014/07/01 职场文书
女性健康知识讲座主持词
2015/07/04 职场文书
MySQL插入数据与查询数据
2022/03/25 MySQL
详解Alibaba Java诊断工具Arthas查看Dubbo动态代理类
2022/04/08 Java/Android