插槽 el-input 数据双向 绑定失效 响应式更新失败
目录
1. 先实现赋值、页面渲染
2. 新增时:初始化独立状态,确保响应式。(可以直接跳到这儿看!)
3. 编辑时--渲染。通过将接口返回的remark值映射到inputValues ,并使用this.$set 确保响应式,(这样才能达到编辑时数据渲染且能修改的效果),编辑
~~~~话多,用于自己给自己解释啦~~~~~ 可以直接跳到这儿去看哦--->2. 新增时:初始化独立状态,确保响应式。
1. 问题:通过map ,给数组a添加remark 字段。但是el-input 是插槽,且备注的数量要根批次号的数量一致,input 实时更新失败且没有渲染到页面上。
2. 方法:定义一个新的变量,如inputValues,用它代替原数组中的remark 。
3. 原因:a 数组中原本没有remark 这个属性,所以当在map 中动态添加这个属性时,Vue 无法检测到这个新增属性的变化,所以导致没有实时更新(因为没有提前对 remark 进行响应式劫持)。
inputValues 能实时更新,是因为它是在data 定义,从一开始就在响应式系统中,它的任何修改(通过$set)都会被 Vue 实时检测到。而且,对 inputValues 的修改全程使用this.$set,这个方法会主动告知 Vue “某个属性 / 索引的值变了”,强制触发响应式更新机制,从而同步到页面。
4. 案例:
1. 先实现赋值、页面渲染
html 代码:
data 中定义 变量
在input事件中,给对应的 stockoutWorkDetailBatchVoList 数组中的备注赋值,如下图。
2. 新增时:初始化独立状态,确保响应式。
关键代码:
async onBatchSelect(val) {let batchList = val.list || [];let rowIndex = this.batchParams.rowIndex ?? 0; // 确保rowIndex有默认值// 重点1:响应式初始化,初始化当前行的inputValues数组(若不存在)if (!Array.isArray(this.inputValues[rowIndex])) {this.$set(this.inputValues, rowIndex, []); //可以强制 Vue 为 rowIndex 这个新属性添加响应式监听,确保后续对 this.inputValues[rowIndex] 的修改能被检测到}// 生成 stockOutWorkDetailBatchVoList 并同步inputValueslet stockOutWorkDetailBatchVoList = batchList.map((item, index) => {const { batchNo, quantity, auxiliaryQuantity, inventoryTypeCode, inventoryTypeName, batchNoFieldInfo } = item;let batchPropertyList = [];if (batchNoFieldInfo) {batchPropertyList = batchNoFieldInfo.split(',').map((item) => {const list = item.split(':');return {label: list[0] || '',value: list[1] || ''};});}// 重点2:安全赋值,确保索引有效,解决数组索引更新的响应式盲区(强制触发响应式更新,告知 Vue “索引 index 的值已修改”,从而同步更新页面)this.$set(this.inputValues[rowIndex], index, ''); return { ...remark: '' // 初始化remark字段};});// 重点3:双重验证:确保所有批次都已在inputValues中初始化stockOutWorkDetailBatchVoList.forEach((item, indexBatch) => {if (indexBatch >= 0 && indexBatch < this.inputValues[rowIndex].length) {this.$set(this.inputValues[rowIndex], indexBatch, item.remark || '');}});
}
3. 编辑时--渲染。通过将接口返回的remark值映射到inputValues ,并使用this.$set 确保响应式,(这样才能达到编辑时数据渲染且能修改的效果),
关键代码:
getDetail(stockOutNo){this.inputValues={}先清空再赋值list.forEach((item, index) => {this.$set(this.inputValues, index, []); // 初始化当前行数组const batchVoList = item.stockOutWorkDetailBatchVoList || [];batchVoList.forEach((itemBatch, indexBatch) => {this.$set(this.inputValues[index], indexBatch, itemBatch.remark || '');});});
}