Vue3 + Element Plus + TypeScript 实现 Tags 标签输入及回显
在开发后台管理系统或表单页面时,动态标签(Tags) 是一个常见的功能需求。用户可以通过输入框添加标签,并通过关闭按钮删除标签,同时还需要支持标签数据的提交和回显。本文将详细介绍如何使用 Vue 3、Element Plus 和 TypeScript 实现这一功能。我们的CSDN发布一栏也是相同的功能。
1. 功能需求
我们需要实现以下功能:
- 动态添加标签:用户可以通过输入框添加新的标签。
- 动态删除标签:用户可以点击标签的关闭按钮删除标签。
- 标签数据提交:将标签数据绑定到表单的
productsLabel
字段,随表单一起提交。 - 标签数据回显:在编辑表单时,从接口获取已保存的标签数据并展示。
2. 技术实现
官网上也有实现方式 https://element-plus.org/zh-CN/component/tag.html
2.1 动态标签的实现
动态标签的核心是通过 v-for
渲染标签列表,并使用 el-tag
组件展示标签。用户可以通过输入框添加新标签,并通过关闭按钮删除标签。
关键代码
<el-form-item label="产品标签" prop="productsLabel">
<el-tag
v-for="tag in dynamicTags"
:key="tag"
class="mx-1"
closable
:disable-transitions="false"
@close="handleClose(tag)"
>
{{ tag }}
</el-tag>
<el-input
v-if="inputVisible"
ref="InputRef"
v-model="inputValue"
class="ml-1 w-20"
@keyup.enter="handleInputConfirm"
@blur="handleInputConfirm"
/>
<el-button v-else class="button-new-tag ml-1" @click="showInput">
+ 添加产品标签
</el-button>
</el-form-item>
代码解析
el-tag
组件:- 使用
v-for
遍历dynamicTags
数组,渲染已添加的标签。 closable
属性为标签添加关闭按钮,点击关闭按钮时触发handleClose
方法。
- 使用
el-input
组件:- 当
inputVisible
为true
时,显示输入框,用户可以在输入框中输入新标签。 - 输入框支持按下回车键(
@keyup.enter
)或失去焦点(@blur
)时触发handleInputConfirm
方法,将输入的内容添加到标签列表。
- 当
el-button
组件:- 当
inputVisible
为false
时,显示“添加产品标签”按钮,点击按钮后显示输入框。
- 当
2.2 标签的添加与删除
标签的添加和删除通过以下方法实现:
关键代码
const inputValue = ref('') // 输入框的值
const dynamicTags = ref<string[]>([]) // 动态标签数组
const inputVisible = ref(false) // 控制输入框的显示
const InputRef = ref<InstanceType<typeof ElInput>>() // 输入框的引用
// 删除标签
const handleClose = (tag: string) => {
dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1)
formData.value.productsLabel = dynamicTags.value // 同步到表单数据
}
// 显示输入框
const showInput = () => {
inputVisible.value = true
nextTick(() => {
InputRef.value!.input!.focus() // 自动聚焦输入框
})
}
// 确认输入
const handleInputConfirm = () => {
if (inputValue.value) {
dynamicTags.value.push(inputValue.value) // 添加新标签
formData.value.productsLabel = dynamicTags.value // 同步到表单数据
}
inputVisible.value = false // 隐藏输入框
inputValue.value = '' // 清空输入框
}
代码解析
handleClose
方法:- 从
dynamicTags
数组中删除指定的标签。 - 将更新后的标签数组同步到表单的
productsLabel
字段。
- 从
showInput
方法:- 显示输入框,并通过
nextTick
确保输入框渲染完成后自动聚焦。
- 显示输入框,并通过
handleInputConfirm
方法:- 将输入框的值添加到
dynamicTags
数组中。 - 将更新后的标签数组同步到表单的
productsLabel
字段。 - 隐藏输入框并清空输入框的值。
- 将输入框的值添加到
2.3 标签数据的回显
在编辑表单时,需要从接口获取已保存的标签数据并回显到页面上。
关键代码
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
if (id) {
formLoading.value = true
try {
formData.value = await ProductsApi.getProducts(id) // 获取表单数据
dynamicTags.value = formData.value.productsLabel || [] // 回显标签数据
} finally {
formLoading.value = false
}
}
}
代码解析
open
方法:- 打开表单弹窗时,如果是编辑模式(
id
存在),则调用接口获取表单数据。 - 将接口返回的
productsLabel
字段赋值给dynamicTags
,实现标签数据的回显。
- 打开表单弹窗时,如果是编辑模式(
2.4 标签数据的提交
标签数据通过 formData.productsLabel
字段随表单一起提交。
关键代码
const submitForm = async () => {
try {
await formRef.value.validate() // 表单验证
formLoading.value = true
const data = formData.value as unknown as ProductsVO
if (formType.value === 'create') {
await ProductsApi.createProducts(data) // 创建产品
} else {
await ProductsApi.updateProducts(data) // 更新产品
}
dialogVisible.value = false
emit('success') // 提交成功后触发事件
} catch (error) {
console.error('表单提交失败:', error)
message.error(t('common.submitFailed'))
} finally {
formLoading.value = false
}
}
代码解析
submitForm
方法:- 在表单提交时,
formData.productsLabel
字段会包含用户添加的所有标签数据。 - 根据
formType
的值,调用创建或更新接口,将标签数据提交到后端。
- 在表单提交时,
3. 注意事项
标签去重:
- 在
handleInputConfirm
方法中,建议添加去重逻辑,避免用户输入重复的标签。例如:if (inputValue.value && !dynamicTags.value.includes(inputValue.value)) { dynamicTags.value.push(inputValue.value) }
- 在
输入框验证:
- 可以为输入框添加验证规则,限制标签的长度或内容格式。例如:
- 限制标签长度:
if (inputValue.value.length > 10) { message.error('标签长度不能超过10个字符') }
- 限制特殊字符:使用正则表达式检查输入内容是否合法。
- 限制标签长度:
- 可以为输入框添加验证规则,限制标签的长度或内容格式。例如:
性能优化:
- 如果标签数量较多,建议使用虚拟滚动(Virtual Scroll)技术优化渲染性能,避免页面卡顿。
- 可以使用
el-tag
的effect
属性(如dark
或light
)优化标签的视觉效果。
用户体验优化:
- 在用户输入标签时,提供实时提示(如“按回车键添加标签”),提升交互体验。
- 在标签数量较多时,可以添加滚动条或分页功能,避免页面布局混乱。
国际化支持:
- 使用
useI18n
实现标签相关文本的国际化,确保多语言环境下功能正常。例如:const { t } = useI18n() const addTagText = t('form.addTag') // 添加标签 const tagLimitText = t('form.tagLimit') // 标签长度不能超过10个字符
- 使用
数据同步:
- 确保
dynamicTags
和formData.productsLabel
的数据同步,避免表单提交时遗漏标签数据。 - 在编辑模式下,从接口获取数据后,及时将
productsLabel
赋值给dynamicTags
,确保标签正确回显。
- 确保
错误处理:
- 在标签添加或删除时,增加错误处理逻辑。例如,如果标签添加失败,可以显示错误提示并恢复原有状态。
浏览器兼容性:
- 测试不同浏览器下的表现,确保功能在主流浏览器(如 Chrome、Firefox、Safari)中正常运行。
4. 总结
通过以上实现,我们完成了动态标签的添加、删除、提交和回显功能。这个功能的核心在于:
- 使用
v-for
动态渲染标签列表。 - 通过
el-input
和el-tag
实现标签的输入和展示。 - 将标签数据绑定到表单的
productsLabel
字段,实现数据的提交和回显。
希望这篇文章对你有帮助!如果有任何问题,欢迎在评论区留言讨论~