像下面这样的jquery是在哪一步实现数据的双向绑定的呢?

新接手一个非常老的项目,还是用jquery写的,由于对jquery接触有限,啃得非常吃力。

<div id="DataBox" data-excludetable="tableData"></div>

HTML里是这样一行代码,在接口获取数据tableData: [{name: 'XXX', M1: 10, M2: 10, total: 20 }]后会在这里填充类似如下表格

名称1月2月合计
XXX101020

其中数量列点击可以变成input进行修改
现在后台对数据进行了修改,将数据来源细分,扩展成了tableData: [{name: 'XXX', part1_M1: 4, part2_M1: 6, M1: 10, part1_M2: 5, part2_M2: 5, M2: 10, total: 20 }]
表格也修改如下,其中来源1/2的月份数据可以进行修改

名称来源1月2月合计
XXX来源145
XXX来源265
XXX合计101020

下面是原来的部分相关代码

// 从接口获取到数据
$("[data-excludetable=tableData]").data("tableData",JSON.stringify(tableData))

// 表单提交的数据
const submitData = $("[data-excludetable=tableData]").data("tableData")

我的理解是这里类似sessionStorage 这样通过tableData这个key对表格数据进行读写。但是很神奇的是数据像是进行双向绑定了一样,输入框填写完毕后提交数据tableData对应的值会随inputvalue进行同步更改,并且我在inputonblur()中也没看到对tableData进行更新。
在我以为这是jquery的双向绑定特性按新需求修改代码后,问题出现在我修改了来源1行的1月(或2月)后,期望更新的是part1_M1(或part2_M1),但是提交修改时通过$("[data-excludetable=tableData]").data("tableData")拿到的对象实际改变的却是M1(M2)的值。而在修改第二行后tableData数据没有进行任何更新。同样地第三行的合计不允许输入修改,但是在前两行修改后会自动计算进行更新,但是这里显然并没有能和M1M2绑定上。
修改后看起来的结果像是jquery只将对应的某行某列与某个字段相关联了,我想知道jquery的这种$("[data-excludetable=xxx]").data()是在哪一步进行的.
下面是生成表格的代码,我也不觉得是在这里实现的。

let tableHtml = `<table class="table">
                      <thead>
                            <tr>
                              <th>名称</th>
                              <th>来源</th>
                              <th>1月</th>
                              <th>2月</th>
                              <th>合计</th>
                            </tr>
                      </thead>
                      <tbody>`
for(var i in tableData) {
    parentHtml+=`<tr data-index="${i}" data-name="${tableData[i].name}">
                      <td rowspan="3">${tableData[i].departmentName}</td>
                      <td>来源1</td>
                      <td data-month="1">${tableData[i].part1_M1}</td>
                      <td data-month="2">${tableData[i].part1_M2}</td>
                  </tr>
                  <tr data-index="${i}" data-name="${tableData[i].name}">
                      <td>来源2</td>
                      <td data-month="1">${tableData[i].part2_M1}</td>
                      <td data-month="2">${tableData[i].part2_M2}</td>`
    parentHtml += `<tr>
                        <td>合计</td>
                        <td data-combined="1"><span>${tableData[i].M1}</span></td>
                        <td data-combined="2"><span>${tableData[i].M2}</span></td>
                        <td><span></span></td>
                    </tr> `
}
    parentHtml +=</tbody></table>

请教一下应该在哪里对症下药,感谢!

阅读 327
avatarAI BotBETA

问题出在数据存储方式与DOM更新的脱节。jQuery的.data()方法本身并没有双向绑定功能,这里实现的是手动数据同步。关键点如下:

  1. 数据存储机制

    // 这里存储的是字符串化的原始数据副本
    $("#DataBox").data("tableData", JSON.stringify(tableData)) 
    
    // 提交时取出的仍是原始字符串
    const submitData = $("#DataBox").data("tableData")
  2. 数据未自动更新的原因
  3. 修改输入框时,原始代码可能通过类似这样的方式更新数据:

    $('td[data-month]').on('blur', 'input', function() {
     const index = $(this).closest('tr').data('index')
     const month = $(this).closest('td').data('month')
     
     // 这里错误地更新了 M1/M2 而不是 partX_M1
     tableData[index]['M' + month] = $(this).val() 
    })
  4. 需要修改的关键点

    // 应该根据行类型判断更新字段
    $('td[data-month]').on('blur', 'input', function() {
     const $row = $(this).closest('tr')
     const index = $row.data('index')
     const sourceType = $row.find('td:first').text() // 获取"来源1/来源2"
     const month = $(this).closest('td').data('month')
    
     // 根据来源类型更新对应字段
     const fieldPrefix = sourceType === '来源1' ? 'part1' : 'part2'
     tableData[index][`${fieldPrefix}_M${month}`] = $(this).val()
    
     // 必须手动更新存储的数据(重要!)
     $("#DataBox").data("tableData", JSON.stringify(tableData))
    })
  5. 合计行自动更新问题
    建议在修改数据后添加计算逻辑:

    function updateTotals() {
     tableData.forEach(item => {
         item.M1 = (+item.part1_M1) + (+item.part2_M1)
         item.M2 = (+item.part1_M2) + (+item.part2_M2)
         item.total = item.M1 + item.M2
     })
    }

修改建议步骤

  1. 在生成表格时为可编辑单元格添加class标识:

    <td data-month="1" class="editable-cell">${tableData[i].part1_M1}</td>
  2. 绑定统一的事件监听:

    $('#DataBox').on('blur', '.editable-cell input', function() {
     // 更新具体字段的逻辑
     // 调用 updateTotals()
     // 更新 .data('tableData')
    })
  3. 提交时需注意:

    // 应该取最新解析后的数据
    const submitData = JSON.parse($("#DataBox").data("tableData"))

这种实现方式本质是手动同步DOM和数据模型,并非真正的双向绑定。需要确保每次修改都显式更新数据存储,并重新计算关联字段。

1 个回答

表格点击时候设置一下断点
表格input失去焦点时候设置一下断点,
data-excludetable搜一下这个相关的代码

function updateCellData($cell, newValue) {
  const $row = $cell.closest('tr');
  const index = $row.data('index');
  const month = $cell.data('month');
  
  let tableData = JSON.parse($("[data-excludetable=tableData]").data("tableData"));
  
  if ($row.find('td:first').text() === '来源1') {
    tableData[index][`part1_M${month}`] = parseFloat(newValue);
    // 更新合计
    tableData[index][`M${month}`] = tableData[index][`part1_M${month}`] + tableData[index][`part2_M${month}`];
  } else if ($row.find('td:first').text() === '来源2') {
    tableData[index][`part2_M${month}`] = parseFloat(newValue);
    // 更新合计
    tableData[index][`M${month}`] = tableData[index][`part1_M${month}`] + tableData[index][`part2_M${month}`];
  }
  
  // 更新总计
  tableData[index].total = tableData[index].M1 + tableData[index].M2;
  
  // 保存回数据存储
  $("[data-excludetable=tableData]").data("tableData", JSON.stringify(tableData));
  
  // 更新显示
  updateDisplayedValues(index);
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题