欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue如何優(yōu)雅地復制一行帶附件的表格數(shù)據(jù)

 更新時間:2025年09月15日 10:17:51   作者:網(wǎng)羅開發(fā)  
在做 Vue 項目的時候,大家是不是經(jīng)常遇到這樣的需求,點一下復制按鈕,把這行表格數(shù)據(jù)復制一份放在下方,除了附件字段之外其他都保留,所以本文我們就來看看如何優(yōu)雅地復制一行帶附件的數(shù)據(jù),不破壞原始數(shù)據(jù)結(jié)構(gòu)吧

前言

在做 Vue 項目的時候,大家是不是經(jīng)常遇到這樣的需求:

“點一下復制按鈕,把這行表格數(shù)據(jù)復制一份放在下方,除了附件字段之外其他都保留。”

聽起來簡單?但一不小心就會踩到“對象引用”的大坑 —— 你以為復制的是一份新數(shù)據(jù),結(jié)果卻把原來的數(shù)據(jù)也一塊改了,尤其是像 poFile 這樣的附件字段,本來是保留原數(shù)據(jù),現(xiàn)在全被你“順手”置空了。

這篇文章就來聊聊:如何優(yōu)雅地復制一行帶附件的數(shù)據(jù),不破壞原始數(shù)據(jù)結(jié)構(gòu)?

需求背景與常見問題

我們有一個表格,每一行代表一個訂單物料。每一行可能有個附件字段 poFile,類型是數(shù)組,像這樣:

{
  id: 'row-1',
  name: '電容',
  amount: 10,
  poFile: [{ name: '報價單.pdf', url: '...' }]
}

現(xiàn)在我們要做一個“復制”功能:

  • 把這行數(shù)據(jù)原樣復制;
  • 附件字段 poFile 需要置空;
  • 原始數(shù)據(jù)不受影響。

于是很多同學很自然地寫了這樣一段邏輯:

const tableobj = dataList.value[index]
tableobj.poFile = [] // 清空附件
dataList.value.splice(index + 1, 0, cloneDeep(tableobj))

表面上看沒問題,但運行完你會發(fā)現(xiàn):原始那一行的 poFile 也被清空了!

為什么?因為你直接修改了原始對象的引用。

背后的 JS 原理小科普:對象是“引用類型”

在 JavaScript 里,對象是引用類型。當你執(zhí)行:

const tableobj = dataList.value[index]

其實 tableobjdataList.value[index] 指向的是同一個對象地址

所以當你:

tableobj.poFile = []

其實也就等于把 dataList.value[index].poFile 清空了。

正確做法:用 cloneDeep 深拷貝新對象

解決這個問題的方法很簡單:

修改前先 cloneDeep 一份副本,所有的“清空字段”都操作副本,原始對象不動。

我們來重寫一下邏輯,分為兩種場景處理:普通復制 和 合并單元格模式復制。

Demo 代碼模塊

import cloneDeep from 'lodash/cloneDeep'

const copyData = (record, index) => {
  let tableobj
  if (props.isMergeCells) {
    const curIndex = dataList.value.findIndex(items => {
      return items.some(item => item.groupId === record.groupId)
    })

    const groupId = generateUUID()
    // cloneDeep 是關(guān)鍵
    tableobj = cloneDeep(dataList.value[curIndex]).map(item => {
      item.id = generateUUID()
      item.groupId = groupId
      item.overLimitApproval = ''
      item.poFile = [] // 附件置空
      return item
    })
    dataList.value.splice(curIndex + 2, 0, ...tableobj, initTotalRow(groupId))
  } else {
    const originalRow = dataList.value[index]
    if (originalRow) {
      const copyRow = cloneDeep(originalRow)
      if (copyRow?.id) {
        delete copyRow.id
        copyRow.groupId = generateUUID()
        copyRow.overLimitApproval = ''
        copyRow.poFile = [] // 清空附件
        dataList.value.splice(index, 0, copyRow)
      }
    }
  }

  emit('edit', { key: 'amount' })
}

拆解講講:為啥這段代碼能解決問題

cloneDeep 是靈魂

lodash/cloneDeep 是做深拷貝的神器,它可以遞歸復制對象中的每一層結(jié)構(gòu),確保你拿到的是一個“全新”的副本。

const copyRow = cloneDeep(originalRow)

這一行就保證了:你對 copyRow 的任何改動,都不會影響原始 originalRow。

清空 poFile 的方式建議用[]而不是''

附件字段通常是數(shù)組,代表可能有多個上傳文件。如果你把它清空成 ''

copyRow.poFile = ''

雖然能通過某些后端校驗,但可能會導致前端的 v-modelel-upload 報錯。

建議統(tǒng)一使用:

copyRow.poFile = []

更符合結(jié)構(gòu)預期,也方便后續(xù)前端判斷文件上傳是否為空。

更進一步:提取清理邏輯為復用函數(shù)

如果將來要清空的字段不止 poFileoverLimitApproval,可以提取成一個統(tǒng)一的清理函數(shù):

function resetCopyFields(row) {
  row.poFile = []
  row.overLimitApproval = ''
  // 其他字段...
  return row
}

調(diào)用時只需要:

resetCopyFields(copyRow)

讓邏輯更清晰,也更方便維護。

實際場景舉例:審批單據(jù)、銷售訂單、費用報銷

這種“復制數(shù)據(jù)行但清空部分字段”的需求在很多系統(tǒng)里都有,比如:

  • 審批系統(tǒng):復制上次填寫的數(shù)據(jù),但需要清空附件和備注;
  • 銷售訂單:客戶下單的某個產(chǎn)品需要復制行修改數(shù)量,附件不帶;
  • 報銷系統(tǒng):上個月差旅報銷復制,但要重新上傳票據(jù)。

這些場景下,如果不小心用了原始對象引用去處理,一不小心就把原始數(shù)據(jù)也改壞了,影響用戶體驗。

總結(jié)

本文通過一個簡單的復制邏輯,講清了一個非常常見但又容易忽略的問題 —— 引用對象修改導致原數(shù)據(jù)被篡改。

最后送上一句話:

只要是對象類型數(shù)據(jù),就別相信“復制了就是新的”這件事,除非你用 cloneDeep

到此這篇關(guān)于Vue如何優(yōu)雅地復制一行帶附件的表格數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Vue復制表格數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論