最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

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

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

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

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

需求背景與常見問題

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

{
  id: 'row-1',
  name: '電容',
  amount: 10,
  poFile: [{ name: '報(bào)價(jià)單.pdf', url: '...' }]
}

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

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

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

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

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

為什么?因?yàn)槟阒苯有薷牧嗽紝?duì)象的引用。

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

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

const tableobj = dataList.value[index]

其實(shí) tableobjdataList.value[index] 指向的是同一個(gè)對(duì)象地址。

所以當(dāng)你:

tableobj.poFile = []

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

正確做法:用 cloneDeep 深拷貝新對(duì)象

解決這個(gè)問題的方法很簡單:

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

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

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 是做深拷貝的神器,它可以遞歸復(fù)制對(duì)象中的每一層結(jié)構(gòu),確保你拿到的是一個(gè)“全新”的副本。

const copyRow = cloneDeep(originalRow)

這一行就保證了:你對(duì) copyRow 的任何改動(dòng),都不會(huì)影響原始 originalRow。

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

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

copyRow.poFile = ''

雖然能通過某些后端校驗(yàn),但可能會(huì)導(dǎo)致前端的 v-modelel-upload 報(bào)錯(cuò)。

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

copyRow.poFile = []

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

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

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

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

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

resetCopyFields(copyRow)

讓邏輯更清晰,也更方便維護(hù)。

實(shí)際場景舉例:審批單據(jù)、銷售訂單、費(fèi)用報(bào)銷

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

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

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

總結(jié)

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

最后送上一句話:

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

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

相關(guān)文章

最新評(píng)論

太谷县| 丹巴县| 赞皇县| 西充县| 察哈| 六枝特区| 宁国市| 察雅县| 昌图县| 东安县| 太湖县| 象州县| 木兰县| 曲阜市| 读书| 松原市| 申扎县| 教育| 长子县| 大城县| 临泉县| 安阳县| 石柱| 宝清县| 平原县| 永修县| 溧水县| 治县。| 大姚县| 娱乐| 贡嘎县| 庆云县| 南充市| 焦作市| 侯马市| 桃园县| 新竹县| 郴州市| 达拉特旗| 宣化县| 珲春市|