2017-08-11 56 views
1

我从Vue的文档的警告部明白,在以下面的方式的阵列来更新值将不起作用:更新值中的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方法中提供的给定的rowcol位置。但是,我的网格中的数据未更新以反映新增值。我如何更新Vue中多维数组中的值?

回答

1

一种方法,该方法的工作原理:

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/[email protected]/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>

如果我想的东西更好,我会在以后更新。

+0

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

2

难度在于您正在以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/[email protected]/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>

+0

好赶上!我没有注意到网格的构建方式。 – Bert

+0

非常好。你能解释为什么使用'push'工作方式不同吗? –

+1

@MahmudAdam出于同样的原因,推荐使用'splice':它是Vue重写的[突变方法]之一(https://vuejs.org/v2/guide/list.html#Mutation-Methods)无功阵列。 –