一. 效果
数据:'["苹果","香蕉"]'
可添加,编辑,删除。
二. 组件源码
html
<template>
<div>
<div v-for="(item, index) in items"
:key="index">
<el-input
v-if="inputVisible && editingIndex === index"
ref="input"
v-model="inputValue"
size="mini"
@keyup.enter.native="handleInputConfirm"
@blur="handleInputConfirm"
/>
<el-tag
v-else
closable
disable-transitions
@close="removeTag(index)"
@click="editTag(index)"
>
{{ item }}
</el-tag>
</div>
<el-input
v-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>
三. 使用组件
html
<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>