在Vue中更新多维数组中的值

Posted

技术标签:

【中文标题】在Vue中更新多维数组中的值【英文标题】:Update value in multidimensional array in Vue 【发布时间】:2018-01-20 12:53:11 【问题描述】:

我从 Vue 文档的警告部分了解到,以下列方式更新数组中的值将不起作用:

  this.arr[idx] = newVal

并且应该使用splice()。我正在使用二维数组来存储网格数据,当单击网格中的单元格时,我很难更新值。

这是我的模板:

  <tr
      v-for="(row, rowKey, index) in grid"
        :key="rowKey">
        <th
          class="row-col-label"
        >rowKey+1</th>
        <td
            v-for="(col, colKey, index) in row"
            :key="colKey"
            @click="selectCell(rowKey, colKey)"
            :class="'selected' : cellSelected(rowKey, colKey)"
        >
        col
        </td>
      </tr>

这里是Vue组件的相关代码:

 created () 
  this.initColHead()
  this.createSpreadSheet()
 ,
 data () 
  return 
   selected: '',
   grid: [],
   colHead: [' '],
   isSelected: false
 
,
methods: 
 initColHead () 
   this.colHead.push(...'ABC'.split(''))
 ,
 createSpreadSheet () 
   for (let i = 0; i <= 2; i++) 
     this.grid[i] = []
      for (let j = 0; j <= 2; j++) 
       this.grid[i][j] = false
      
   
 ,
selectCell (row, col) 
  this.isSelected = true
  console.log(`row $row col $col`)
  this.grid[row].splice(col, 1, true)
  for (let i = 0; i <= 2; i++) 
    for (let j = 0; j <= 2; j++) 
      console.log(this.grid[i][j])
    
  
,
cellSelected (row, col) 
  return (this.grid[row][col] === true)


所以我试图将true 值添加到单击我的selectCell 方法中提供的给定row col 位置的单元格。但是,我的网格中的数据没有更新以反映新增加的值。 Vue 中的多维数组究竟如何更新值?

【问题讨论】:

【参考方案1】:

困难在于您构建数组的方式是 Vue 不会使其行反应。您可以构建数组,然后将其作为一个整体分配给数据项,以便 Vue 使其具有响应性,或者您可以使用 push 构建数组(最后是行),这将使它们具有响应性。然后您可以使用splice 修改单个元素。修改Bert的例子:

console.clear()


new Vue(
  el: "#app",
  created() 
    this.initColHead()
    this.createSpreadSheet()
  ,
  data() 
    return 
      selected: '',
      grid: [],
      colHead: [' '],
      isSelected: false
    
  ,
  methods: 
    initColHead() 
      this.colHead.push(...'ABC'.split(''))
    ,
    createSpreadSheet() 
      for (var i = 0; i <= 2; i++) 
        this.grid.push([]);
        for (var j = 0; j <= 2; j++) 
          this.grid[i].push(false);
        
      
    ,
    selectCell(row, col) 
      this.grid[row].splice(col, 1, true);
    ,
    cellSelected(row, col) 
      return (this.grid[row][col] === true)
    
  
)
.selected 
  background-color: green;
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  <table>
    <tr v-for="(row, rowKey, index) in grid" :key="rowKey">
      <th class="row-col-label">rowKey+1</th>
      <td v-for="(col, colKey, index) in row" :key="colKey" @click="selectCell(rowKey, colKey)" :class="'selected' : cellSelected(rowKey, colKey)">
        col
      </td>
    </tr>
  </table>
</div>

【讨论】:

好收获!我没有注意到网格是如何构建的。 非常好。你能解释一下为什么使用push 会有不同的效果吗? @MahmudAdam 与推荐 splice 的原因相同:它是 Vue 为反应式数组重新编写的 mutation methods 之一。【参考方案2】:

一种有效的方法:

selectCell (row, col) 
  //make a copy of the row
  const newRow = this.grid[row].slice(0)
  // update the value
  newRow[col] = true
  // update it in the grid
  this.$set(this.grid, row, newRow)
,

这是一个例子。

console.clear()


new Vue(
  el: "#app",
  created() 
    this.initColHead()
    this.createSpreadSheet()
  ,
  data() 
    return 
      selected: '',
      grid: [],
      colHead: [' '],
      isSelected: false
    
  ,
  methods: 
    initColHead() 
      this.colHead.push(...'ABC'.split(''))
    ,
    createSpreadSheet() 
      for (let i = 0; i <= 2; i++) 
        this.grid[i] = []
        for (let j = 0; j <= 2; j++) 
          this.grid[i][j] = false
        
      
    ,
    selectCell(row, col) 
      const newRow = this.grid[row].slice(0)
      newRow[col] = true
      this.$set(this.grid, row, newRow)
    ,
    cellSelected(row, col) 
      return (this.grid[row][col] === true)
    
  
)
.selected 
  background-color: green;
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  <table>
    <tr v-for="(row, rowKey, index) in grid" :key="rowKey">
      <th class="row-col-label">rowKey+1</th>
      <td v-for="(col, colKey, index) in row" :key="colKey" @click="selectCell(rowKey, colKey)" :class="'selected' : cellSelected(rowKey, colKey)">
        col
      </td>
    </tr>
  </table>
</div>

如果我想到更好的东西,我会稍后更新。

【讨论】:

谢谢!。我最终做的是 this.grid = this.grid.map(el => el.splice()) 以便在设置新值后更新整个网格并且它似乎正在工作;但是,您的解决方案看起来好多了。

以上是关于在Vue中更新多维数组中的值的主要内容,如果未能解决你的问题,请参考以下文章

动态获取/设置多维数组中的值的函数

如何从Vue中的多维数组中提取数据?

php改变多维数组的值

PHP按多维数组中的值排序[重复]

多维数组 Vue 2 中的奇怪行为

main() 打印出与paint() 不同的多维数组的值