实现如下图所示的一个标签选择组件。
图1:标签选中时的效果
图2:标签新建时的效果
实现
tagSelect.vue
<template>
<div class="sys-tag">
<el-popover :visible-arrow="false" :offset="-50" width="600" v-model="tagVisible">
<div style="padding: 10px">
<el-tag class="select-tag pointer" :color="tag.color" effect="dark" closable v-for="(tag, index) in selected"
:key="index" @close="closeLabel(index)">{{ tag.labelName }}</el-tag>
<span style="color: #aaa" v-if="selected">还可以添加{{ 6 - selected.length }}个标签</span>
<div style="padding: 10px 0">
<el-input v-model="labelName" clearable style="width: 300px" placeholder="添加标签"
@keyup.enter.native="addLabel"></el-input>
</div>
<div v-show="labelName">
<div style="padding: 10px">选择一个颜色</div>
<div @click="color = item" class="color-item pointer" :style="'background-color:' + item"
v-for="(item, index) in colorList" :key="index">
<i v-if="color == item" class="el-icon-check pos-center"></i>
</div>
<div style="clear: both; padding: 10px">
<el-button type="primary" @click="addLabel">新建</el-button>
</div>
</div>
<div v-show="!labelName" style="max-height: 250px; height: auto; overflow-y: auto">
<el-tag class="select-tag pointer" v-for="(item, index) in tags" :key="index" :color="item.color" effect="dark"
:hit="false" @click="selectLabel(item)">{{ item.labelName }}</el-tag>
</div>
</div>
<div slot="reference" v-show="!readonly" style="display: inline">
<el-tag class="select-tag pointer" :color="tag.color" effect="dark" v-for="tag in selected" :key="tag.labelID">{{
tag.labelName }}</el-tag>
<el-button icon="el-icon-circle-plus-outline" size="mini" type="text">添加标签</el-button>
</div>
</el-popover>
<template v-if="readonly">
<el-tag class="select-tag" :color="tag.color" effect="dark" v-for="tag in labList" :key="tag.labelID">{{
tag.labelName }}</el-tag>
<el-tag class="select-tag" v-if="labList && 0 == labList.length" type="info">暂无标签</el-tag>
</template>
</div>
</template>
<script>
export default {
props: {
readonly: {
type: Boolean,
default: false
},
labList: {
type: Array,
default: () => []
}
},
data() {
return {
color: "#F6C600",
labelName: "",
tagVisible: false,
tags: [
{ labelID: 1, labelName: "标签1", color: "#F6C600" },
{ labelID: 2, labelName: "标签2", color: "#EF7F00" },
{ labelID: 3, labelName: "标签3", color: "#F29596" }
],
selected: [],
colorList: [
"#F6C600",
"#EF7F00",
"#F29596",
"#EC453C",
"#8A43E1",
"#87CB4C",
"#43A79E",
"#73B8EE",
"#3C80E8",
"#21317B"
]
};
},
computed: {},
created() { },
mounted() {
this.initLab(this.labList);
},
methods: {
initLab(val) {
this.selected = val ? val : [];
},
addLabel() {
if (this.labelName) {
let data = {
labelName: this.labelName,
labelID: Date.parse(new Date()).toString(),
color: this.color
};
// 先显示标签
this.selected.push(data);
this.tags.push(data);
}
// ---- 这里请求接口添加标签 ----
},
// 返回选中的值
confirm() {
// this.$emit("select", this.selected);
},
// 关闭标签
closeLabel(index) {
this.selected = this.selected.filter((item, newIdx) => {
return newIdx != index;
});
this.confirm();
},
// 选中标签
selectLabel(tag) {
let isRepeat = false;
this.selected.map(item => {
if (tag.labelID == item.labelID) {
isRepeat = true;
return;
}
});
if (!isRepeat && this.selected && this.selected.length < 6) {
this.selected = this.selected.concat([tag]);
this.confirm();
}
}
}
};
</script>
<style>
.pos-center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.pointer {
cursor: pointer;
}
.el-tag--dark {
border-color: #fff;
}
.select-tag {
margin-top: 5px;
margin-bottom: 5px;
}
.color-item {
width: 40px;
height: 30px;
border-radius: 5px;
float: left;
margin: 5px;
position: relative;
color: #fff;
}
</style>