在动态表单的开发场景中,我们经常会遇到需要为输入元素添加序号标识的需求,比如多个联系方式输入框、多条地址录入项等,通常会把序号信息放在输入元素的title属性中方便用户查看。当表单支持动态新增、删除输入项时,如果不及时更新title属性,就会出现序号和实际元素位置不匹配的问题,比如删除了第二个输入框,后面输入框的title还是原来的序号,造成用户认知混乱。

核心实现思路
要实现title属性的动态更新维持序号一致性,核心逻辑分为三步:
- 监听表单输入项的增删操作,在每次操作后触发序号重算逻辑
- 遍历当前所有存在的输入元素,按照其在表单中的实际位置重新计算序号
- 将新的序号同步更新到每个输入元素的
title属性中
原生JavaScript实现示例
以下是一个原生JavaScript实现的动态表单示例,支持新增和删除输入项,同时自动维护title属性的序号一致性:
// 获取表单容器
const formContainer = document.getElementById('form-container');
// 获取新增按钮
const addBtn = document.getElementById('add-btn');
// 更新所有输入元素的title属性序号
function updateTitleIndex() {
// 获取容器内所有的输入框
const inputs = formContainer.querySelectorAll('input[type="text"]');
// 遍历输入框,按位置更新title
inputs.forEach((input, index) => {
// 序号从1开始,所以index+1
input.title = `第${index + 1}个联系方式`;
});
}
// 新增输入项
addBtn.addEventListener('click', () => {
// 创建新的输入容器
const itemDiv = document.createElement('div');
itemDiv.className = 'form-item';
// 创建输入框
const input = document.createElement('input');
input.type = 'text';
input.placeholder = '请输入联系方式';
// 创建删除按钮
const deleteBtn = document.createElement('button');
deleteBtn.type = 'button';
deleteBtn.textContent = '删除';
// 绑定删除事件
deleteBtn.addEventListener('click', () => {
itemDiv.remove();
// 删除后更新序号
updateTitleIndex();
});
// 组装元素
itemDiv.appendChild(input);
itemDiv.appendChild(deleteBtn);
formContainer.appendChild(itemDiv);
// 新增后更新序号
updateTitleIndex();
});
// 初始加载时更新一次序号
updateTitleIndex();
对应的HTML结构如下:
<div class="form-wrapper">
<button type="button" id="add-btn">新增联系方式</button>
<div id="form-container">
<!-- 初始可以有一个默认输入项 -->
<div class="form-item">
<input type="text" placeholder="请输入联系方式" />
<button type="button" class="delete-btn">删除</button>
</div>
</div>
</div>
Vue框架中的实现示例
如果使用Vue框架开发,可以借助响应式数据和列表渲染的特性更简洁地实现这个功能:
// Vue组件逻辑
export default {
data() {
return {
// 输入项列表,每个元素对应一个输入项
inputList: [
{ id: 1, value: '' }
],
nextId: 2
};
},
methods: {
// 新增输入项
addInput() {
this.inputList.push({
id: this.nextId,
value: ''
});
this.nextId++;
},
// 删除输入项
deleteInput(index) {
this.inputList.splice(index, 1);
}
}
};
对应的模板代码如下:
<template>
<div class="form-wrapper">
<button type="button" @click="addInput">新增联系方式</button>
<div class="form-item" v-for="(item, index) in inputList" :key="item.id">
<input
type="text"
v-model="item.value"
:title="`第${index + 1}个联系方式`"
placeholder="请输入联系方式"
/>
<button type="button" @click="deleteInput(index)">删除</button>
</div>
</div>
</template>
在Vue的实现中,由于inputList是响应式数组,当数组新增或删除元素时,v-for的index会自动更新,绑定的title属性也会同步刷新,不需要额外手动调用更新函数,逻辑更加简洁。
注意事项
在实际开发中还需要注意几个细节:
- 如果输入项有拖拽排序的需求,需要在排序完成后重新触发序号更新逻辑,保证
title和最终位置匹配 - 序号的计算规则可以根据业务需求调整,比如不需要从1开始,或者需要跳过某些隐藏的输入项,遍历时可以增加对应的过滤条件
- 如果表单输入项类型不统一,比如混合了
<input>、<textarea>等元素,遍历时可以使用更通用的选择器,比如formContainer.querySelectorAll('[data-input-item]'),给需要维护序号的元素统一添加自定义属性来筛选
通过以上方法,就可以在动态表单场景中稳定维护输入元素title属性的序号一致性,提升表单的交互体验。