使用element-ui实现添加标签tag小组件

先吐个槽:
input可以获取焦点,可以自动选中,却不能自适应文本宽度;
contenteditable可以自适应文本宽度却不能调用focus()和select()!
要达到新增一个标签时选中示范文本并更改的需求还真是坎坷啊。。。

正文开始:

环境:vue-cli, element-ui

这里选用contenteditable的方式,自适应还是更美观一些:
首先分析一下contenteditable的自动全选:

let range = document.createRange(); 
range.selectNodeContents(newtag);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);

range是我们创建的需要选定的区域,而selection是屏幕上已经被选定的区域,range可以通过addRange方法添加到屏幕上,看到的效果就是自动选中了。
selectNodeContents可以选择父元素不包括元素本身的所有子元素,利用这个可以实现一个根据文本自适应的输入框,在外层再包一层div,方便hover的时候右上角小叉叉删除键定位。

先写个界面,用上elementui让他好看一点,叉叉就用里面自带的icon了:

<template>
	<div>
		<template v-for="(item,index) in tags"> 
			<div class='el-button primary el-button--mini is-plain newtag' 
			 @mouseenter="showCloseBtn(index)" @mouseleave="hideCloseBtn(index)">
				<div contenteditable="plaintext-only" class="newtag-content" :ref='`newTag${index}`' @blur="checkTag(index)">
					{{ item }}
				</div>
				<i class="close-i el-icon-circle-close" :ref="`closeI${index}`" @click="removeTag(index)"></i>
			</div>
		</template>
		<i class="el-icon-circle-plus-outline" @click="addTag()"></i>
	</div>
</template>

需要绑定的方法:
checkTag: 如果新增tag没有内容,则点击空白处tag消失;
showCloseBtn: 鼠标移入tag叉叉出现;
hideCloseBtn: 鼠标移出tag叉叉消失;
removeTag:点击tag右上角叉叉删除本tag;
addTag:点击加号icon新增tag,同时自动全选文本。

另外再给每个tag和icon加上个与循环index相关的ref,方便取元素。

实现方法,补上css:

<script>
	export default {
		data() {
			return {
				tags:['川建国','奥观海'], //通过操作数组数据直接增减tag
			}
		},
		methods:{
			addTag() {
				this.recForm.tags.push('新标签');
				this.$nextTick(()=>{
					let len = this.recForm.tags.length;
					let newtag = this.$refs[`newTag${len-1}`][0]; //获得新增的标签,数组的最后一个
					let range = document.createRange();
					range.selectNodeContents(newtag);
					window.getSelection().removeAllRanges();
					window.getSelection().addRange(range); //自动全选
				});
			},
			showCloseBtn(index){
				this.$refs[`closeI${index}`][0].style.display = 'block'; //显示叉叉
			},
			hideCloseBtn(index){
				this.$refs[`closeI${index}`][0].style.display = 'none';  //叉叉消失
			},
			checkTag(index){ //判断tag有无内容
				let text = this.$refs[`newTag${index}`][0].innerText.trim();
				if(text.length==0){
					this.recForm.tags.pop();
				}else{
					this.recForm.tags[index] = text;
				}
			},
			removeTag(index){  //删除叉叉
				this.recForm.tags.splice(index,1);
			},
		}
	}
</script>
<style scoped>
.close-i{
		position: absolute;
		top:-8px;
		right: -9px;
		display: none;
		cursor: pointer;
		font-size: 18px;
		background-color: white;
		border-radius: 10px;
	}
	.newtag{
		position: relative;
		cursor: text;
		overflow: visible;
		display: inline-block;
		padding: 0;	//将原本padding 7px 15px 移到内层,这样鼠标点选位置会大一些,
	}
	.newtag-content{
		margin: 7px 15px; 
	}
</style>

最终效果图:
在这里插入图片描述

你可能感兴趣的:(使用element-ui实现添加标签tag小组件)