分析
我们自己封装input输入标签需要注意一下几点:
- 样式实现,span实现标签效果、input隐藏边框(Element-UI可以直接使用tag)。
- 事件监听,确定生成标签的操作,可以是回车,并且需要监听离开焦点的情况。
- 标签限制,最多几个,以及输入验证
- html:
<template> <!-- 外层div --> <div ref="arrbox" :style="{width:`${width}px`}" class="arrbox" @click="onclick"> <!-- 标签 Element-UI --> <el-tag v-for="(item,index) in tagsArr" :key="index" type="info" closable @close="removeTag(index)">{{ item }}</el-tag> <!-- 标签 自定义的标签样式 --> <!-- <div v-for="(item,index) in tagsArr" :key="index" class="spanbox"> <span class="tagspan">{{item}}</span> <i class="spanclose" @click="removeTag(index)"></i> </div> --> <!-- 输入框 --> <input ref='tagInput' v-model="currentval" :placeholder="placeholder" class="tagInput" type="text" :style="{height:`${height}px`}" @keyup="keyupFn" @blur="addTags('bulr')" > </div> </template>
- js:
- 首先我们需要在点击最外层的div时,让input聚焦
- 在css样式上,我们让input和那些tag使用flex布局放在一行,并加上换行属性,同时设置input最小宽度和flex:1,这样就可以让input一直更在tag后面,宽度小于定义的最小宽度时也会自动换行
- 需要监听空格和回车,以及失焦,将input的值放到tag数组里面,然后清空tag.
- 在添加tag的时候加一些限制,这样可以更好的用户操作
export default { name: 'tagInput', model: { prop: 'parentArr', event: 'change-parentArr' }, props: { width: { type: Number, default: 300 }, height: { type: Number, default: 40 }, parentArr: { type: Array, default() { return [] } }, limit: { // 最多生成标签数 type: Number, default: -1 }, placeholder: { type: String, default: '请输入' }, reg: { type: String, default: '' } }, data() { return { currentval: '', tagsArr: [], inputLength: '' } }, watch: { tagsArr(value) { this.$emit('change-parentArr', value) }, parentArr: { handler(value) { this.tagsArr = value }, deep: true, immediate: true } }, mounted() { }, methods: { removeTag(index) { this.tagsArr.splice(index, 1) }, // 监听按键,空格或者Enter keyupFn(e) { if (e.code == 'Space' || e.keyCode == 32) { this.currentval = this.currentval.slice(0, -1) this.addTags() } if (e.key == 'Enter' || e.keyCode == 13) { this.addTags() } }, addTags(type = 'click') { if (this.limit != -1 && this.tagsArr.length >= this.limit) { this.$message.warning(`只能输入${this.limit}个`) return } if (this.tagsArr.indexOf(this.currentval) > -1) { if (type == 'click') { this.$message.warning(`已经输入了【${this.currentval}】`) } else { this.currentval = '' } return } // 格式校验 if (this.reg != '') { if (!this.reg.test(this.currentval)) { this.$message.warning('格式不正确!') this.currentval = '' return } } this.tagsArr.push(this.currentval) this.tagsArr = this.tagsArr.filter(n => n != '') this.currentval = '' }, onclick() { this.$nextTick(() => { this.$refs.tagInput.focus() }) } } }
- css:
input::-webkit-input-placeholder { /* placeholder颜色 */ color: #c1c7cf; /* placeholder字体大小 */ font-size: 14px; } .arrbox { box-sizing:border-box; background-color: white; border: 1px solid #dcdee2; border-radius: 4px; font-size: 12px; text-align: left; word-wrap: break-word; overflow: hidden; display: inline-flex; flex-wrap: wrap; align-items: center; } /* input */ .tagInput { font-size: 12px; border: none; box-shadow: none; outline: none; background-color: transparent; min-width: 40%; color: #495060; flex: 1; margin-left: 15px; } .el-tag{ height: 25px; line-height: 25px; margin: 5px 3px; } /* 自定义的标签 */ .spanbox { display: inline-block; font-size: 14px; margin: 3px 4px 3px 0; background-color: #f7f7f7; border: 1px solid #e8eaec; border-radius: 3px; } .tagspan { height: 24px; line-height: 22px; max-width: 99%; position: relative; display: inline-block; padding-left: 8px; color: #495060; font-size: 12px; cursor: pointer; opacity: 1; vertical-align: middle; overflow: hidden; transition: 0.25s linear; } .spanclose { padding: 0 10px 5px 0; opacity: 1; -webkit-filter: none; filter: none; } .spanclose:after { content: "x"; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; line-height: 27px; }
- 使用:
<template>
<tagInput v-model="from.tag" :width="302" placeholder="请输入标签" />
</template>
<script>
import tagInput from ./tagInput'
export default {
components: {
tagInput
},
data(){
return{
from:{
tag:[]
}
}
}
}
</script>