Vue中数组的【响应式】操作

发布于:2024-06-27 ⋅ 阅读:(134) ⋅ 点赞:(0)

在 Vue.js 中,当你修改数组时,Vue 不能检测到以下变动的数组:

  1. 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength

为了解决这个问题并确保你的数组变动是响应式的,Vue 提供了一些变异方法,你可以使用它们来修改数组:

7个保证响应式方法(这些方法会触发视图更新):

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

方法详解:

在 Vue.js 中,为了使得数组的变动是响应式的,Vue 提供了一些特定的数组方法来修改数组,这些方法会触发视图的更新。以下是 Vue 中用于数组响应式的 7 个方法及其详解:

  1. push(item1, ..., itemN)
    • 向数组的末尾添加一个或多个元素,并返回新的长度。
    • 示例:this.array.push(item);
  2. pop()
    • 删除并返回数组的最后一个元素。
    • 示例:let lastItem = this.array.pop();
  3. shift()
    • 删除并返回数组的第一个元素。
    • 示例:let firstItem = this.array.shift();
  4. unshift(item1, ..., itemN)
    • 向数组的开头添加一个或多个元素,并返回新的长度。
    • 示例:this.array.unshift(item);
  5. splice(index, deleteCount, item1, ..., itemN)
    • 通过删除或替换现有元素或者添加新元素来改变一个数组的内容。
    • index(必需):开始改变的索引。
    • deleteCount(必需):整数,表示要移除的数组元素的个数。
    • item1, ..., itemN(可选):要添加进数组的元素,从index 位置开始。
    • 示例:this.array.splice(2, 0, 'a', 'b'); // 在索引 2 的位置插入 'a' 和 'b'
  6. sort(compareFunction)
    • 对数组的元素进行排序,并返回数组。
    • compareFunction(可选):用来指定按某种顺序进行排序的函数。如果省略,元素将按照转换为的字符串的 Unicode 码点顺序进行排序。
    • 示例:this.array.sort((a, b) => a - b); // 从小到大排序
  7. reverse()
    • 颠倒数组中元素的顺序。
    • 示例:this.array.reverse();

注意

  • 使用以上方法修改数组时,Vue 将能够检测到这些变化,并触发相应的视图更新。
  • 但是,如果你使用索引直接设置数组项(例如 this.array[indexOfItem] = newValue)或使用 length 属性来修改数组长度,Vue 则不能检测到这些变化。
  • 在 Vue 3 中,响应式系统有所改变,但基本的数组响应式方法仍然适用。Vue 3 引入了 Composition API,你可以使用 reactive 或 ref 来创建响应式数组,并使用上述方法来修改它们。
  • 如果你需要直接修改数组中的某个元素(使用索引),你可以使用 Vue.set(在 Vue 2 中)或 reactive 搭配 Proxy(在 Vue 3 中)来确保变化是响应式的。但在大多数情况下,使用上述的数组方法更为简单和直观。

但是,如果你需要直接修改数组中的某个元素(使用索引),或者你需要替换整个子数组,你需要确保这种变化也是响应式的。有几种方法可以处理这种情况:

  1. 使用 Vue 的 Vue.set() 方法(在 Vue 2.x 中)或 this.$set() 实例方法(在 Vue 组件内部)。但是,对于数组,这主要用于添加新属性到响应式对象上,而不是用于直接修改数组项。

  2. 使用 splice() 方法替换数组中的某个元素或子数组。

对于替换数组中的子数组(即你提到的“列”),你可以使用 splice() 方法,但你需要遍历外层数组,并对每个子数组执行 splice()。例如:

methods: {  
  replaceColumn(columnIndex, newColumn) {  
    this.multiArray.forEach(row => {  
      // 假设 newColumn 的长度与 row 的长度相匹配,或者你只需要替换部分项  
      row.splice(columnIndex, row.length - columnIndex, ...newColumn);  
    });  
  }  
}

在上面的例子中,multiArray 是一个二维数组,columnIndex 是你想要替换的列的索引,newColumn 是一个新数组,包含了替换后的值。

  • 使用计算属性或方法来返回一个新的数组,而不是直接修改原始数组。这种方法不会改变原始数组,但会基于原始数组创建一个新的响应式数组。

请注意,从 Vue 3 开始,响应式系统进行了重写,引入了 reactive 和 ref API。如果你使用的是 Vue 3,你可能会使用 Composition API 和这些新的响应式 API 来处理数组。但是,基本的响应式原则仍然适用,即使用 Vue 提供的变异方法来确保视图更新。

 案例:

需求:修改3*5数组,第一列保留原来数据,后面用一个3*4的数组【后端响应】替换原有值

  •  刚开始直接替换数组各个单元格的值,数组数据是变化了,但是不是响应式,无法导致依赖此数据的视图发生改变
// // 更新原始数组,保留第一列,并用3x4矩阵替换其余列
              for (let i = 0; i < that.tableData.length; i++) {
                // 保留第一列的值
                let firstColumnValue = that.tableData[i][0];

                // 替换后面的列
                for (let j = 1; j < that.tableData[i].length; j++) {
                  // 如果j的值超过了replacementMatrix的列数,则停止替换(可选)
                  if (j > replacementArr[i].length) {
                    break;
                  }
                  that.tableData[i][j] = replacementArr[i][j - 1]; // 减去1是因为replacementMatrix的索引从0开始
                }
              }
  • 然后试着用splice()[可行,为响应式] 
              that.tableData.forEach((item,rowIndex)=>{
                //splice():array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
                item.splice(1,item.length-1,...replacementArr[rowIndex])
              })