一. 效果
数据:‘[“苹果”,“香蕉”]’
可添加,编辑,删除。
二. 组件源码
<template><div><div v-for="(item, index) in items":key="index"><el-inputv-if="inputVisible && editingIndex === index"ref="input"v-model="inputValue"size="mini"@keyup.enter.native="handleInputConfirm"@blur="handleInputConfirm"/><el-tagv-elseclosabledisable-transitions@close="removeTag(index)"@click="editTag(index)">{{ item }}</el-tag></div><el-inputv-if="inputVisible && editingIndex === null"ref="input"v-model="inputValue"size="mini"@keyup.enter.native="handleInputConfirm"@blur="handleInputConfirm"/><el-button v-else size="small" @click="showInput">+ 添加</el-button></div>
</template><script>
export default {name: "EditableTags",props: {// 接收一个 JSON 数组字符串作为初始值initialItems: {type: String,default: '[]'}},data() {return {// 解析初始值items: JSON.parse(this.initialItems),inputVisible: false,inputValue: '',editingIndex: null};},watch: {// 监听 initialItems 的变化initialItems: {handler(newItems) {this.items = JSON.parse(newItems);},immediate: true},// 监听 items 的变化,触发父组件的更新事件items: {handler(newItems) {this.$emit('update:items', JSON.stringify(newItems));},deep: true}},methods: {removeTag(index) {this.items.splice(index, 1);},editTag(index) {this.editingIndex = index;this.inputValue = this.items[index];this.inputVisible = true;this.$nextTick(() => {this.$refs.input[0].focus();});},showInput() {this.inputVisible = true;this.$nextTick(() => {this.$refs.input.focus();});},handleInputConfirm() {if (this.inputValue) {if (this.editingIndex !== null) {this.items[this.editingIndex] = this.inputValue;// 由于watch监控不到数组元素值的变化, 所以手动通知this.$set(this.items, this.editingIndex, this.inputValue);this.editingIndex = null;} else {this.items.push(this.inputValue);}}this.inputVisible = false;this.inputValue = '';}}
};
</script><style scoped>
.el-tag {margin-right: 10px;
}
</style>
三. 使用组件
<template><editable-tags :initial-items='items' @update:items="newItems => items = newItems" />
</template><script>
import EditableTags from "editableTags";export default {components: {EditableTags},data() {return {items: '["苹果","香蕉"]',}}
};
</script>