vue组件系列-Tags input

前言

最近做后台系统的组件化开发,借机和@二胖手同学一起开发了一个基于vue的开源组件库,方便后期使用,目前该项目正在持续开发中。

介绍

大家可能遇到过一种需求,让用户输入以某个特殊字符分隔的字符串,如java,php就是以西文逗号分隔,这种输入需要用户自行添加内容之间的特殊分隔符,其实完全可以换用一种用户体验更好的方式解决。
不知道大家管下面这种叫什么,我称之为Tags input。
《vue组件系列-Tags input》
其实,当大家在SF写文章的时候就会有这类标签选择框。体验地址

实现

scss

//输入框tags
.tags-wrap{
  width: 100%;
  height: 100%;
  outline: none;
  &::after{
    content: "";
    display: block;
    height: 0;
    clear: both;
    }
}
.tags, .tags-input{
  position: relative;
  float: left;
  color: #fff;
  line-height: 28px;
  margin: 0 4px 4px 0;
  padding: 0 22px 0 10px;
  border-radius: 6px;
  .content{
    line-height: 28px;
  }
  .del{
    width: 22px;
    height: 28px;
    text-align: center;
    cursor: pointer;
    position: absolute;
    top: -1px;
    right: 0;
  }
}
.tags-input{
  font-size: 14px;
  padding: 0;
  background-color: inherit;
  border: none;
  color: inherit;
  width: 10em;
}

整个Tags input输入框的宽度由组件的父元素决定,高度由Tags自身决定,会根据内容自动撑开。

vue组件

vue template

  <div class="input tags-wrap">
    <div class="tags" transition="tags" :style="{backgroundColor: bgc[item.bgc_no]}" v-for="item in dis_source">
      <span class="content">{{item.text}}</span><span class="del" @click="del($index, false)">&times;</span>
    </div>
    <input class="tags-input" type="text" placeholder="标签,按 enter 创建" v-model="text" @keyup.enter="add(text)" @keydown.delete="del(source.length - 1, true)">
  </div>

v-for是vue的遍历数组方法,:style用来绑定样式,@click@keyup这些都是绑定事件的语法。

vue data

props: {
  source: {
    type: Array,
    default: []
  }
},
data() {
  var dis_source = []
  this.source.forEach(function (item) {
    var obj = {
      text: item,
      bgc_no: Math.ceil(Math.random() * 10) - 1
    }
    dis_source.push(obj)
  })
  return {
    text: '',
    bgc: ['#e961b4', '#ed664b', '#7b6ac7', '#56abd1', '#f7af4c', '#fe5467', '#52c7bd', '#a479b7', '#cb81ce', '#5eabc5'],
    dis_source: dis_source
  }
}

数据有两部分,props来源于父组件,用于同步父子组件的内容,data中的是经过我处理的用于展示的数据,为每个标签添加随机的背景色。

vue methods

  add(text){
    if(text != ''){
      var count = this.source.length
      this.source.$set(count, text)
      this.dis_source.$set(count, {
        text: text,
        bgc_no: Math.ceil(Math.random() * 10) - 1
      })
      this.text = ''
    }
  },
  del(index, way){
    if(way){
      if(index >=0 && this.text == ''){
        this.source.splice(index, 1)
        this.dis_source.splice(index, 1)
      }
    }else {
      this.source.splice(index, 1)
      this.dis_source.splice(index, 1)
    }
  }

就这个组件而言只需要增加/删除tags两个方法,我在模版中删除tags的方法分为两种,两种的处理情况略有不同要加以判断。

使用

html:
  <div id="app">
    <v-tags :source.sync="source"></v-tags>
  </div>

js:
  var app = new Vue({
    el: '#app',
    data: {
      source: ['英雄联盟', '骚猪', '对对对对对我是娇妹', '小轩在不在']
    },
    components: {
      'v-tags': tags
    }
  })

使用时只要把vue和我的组件引入,就可以在页面中使用自定义的v-tags标签,同时把数据传给子组件并且加上.sync保持数据与子组件同步。在该组件中,用户可以在标签框中输入内容后按下enter即可添加新标签,使用delete删除处于末尾的标签,或者也可以点击标签后面的叉叉删除标签。
除了这个组件之外,我们还开源了其他组件,并且在逐步完善组件库,其他组件也会有系列文章推出,欢迎关注我和@二胖手的专栏,提出意见,或者你期望增加的组件,项目地址:web-style

    原文作者:BingqiChen
    原文地址: https://segmentfault.com/a/1190000005779273
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞