Skip to content

数组对象遍历

作者:Yuan Tang
更新于:5 个月前
字数统计:1.1k 字
阅读时长:3 分钟

需求

开发前先看一下需求捋一下思路,得到的数据如下所示:

需求

一个对象内有三个属性,每个属性为逗号隔开的字符串,每一条一一对应。需要实现的效果是下面这种方式:

效果

通过遍历渲染到页面中,每一条数据对应一个输入框输入内容。

因此,通过分析,得出结论,需要做的是把得到的对象转为数组对象,每一项数据要一一对应,格式如下所示:

js
productNumberVeList:[
  {
    productid: '1623171665095598081',
     	productName: 'BM208玛瑙啡',
     	imageUrl: 'picture\\B\\BM208玛瑙啡-200x300.jpg',
     	productName: 'BM208玛瑞啡',
     	productNumber: '12'
  },
  {
    productid: '1623171665120763996',
    productName: 'BM266岭南灰',
    imageUrl: 'picture\\M\\MBM266岭南灰-200x300mm.jpg',
    productName: 'BM266岭南灰',
    productNumber: '34'
  }
]

转数组

思路

  1. 定义一个空数组 arr
  2. 遍历获取到的对象,获取每一项的 keyvalue 值。
  3. 通过字符串 .split(',') 的方法,把获取到的值转为数组,forEach 遍历。
  4. 判断空数组 arr 当前索引有没有值,没有值则新建一个对象赋值 push 追加;有值则为该索引的对象赋值。
  5. 最后添加即可。

实现

定义空数组

js
productCallback(row) {
  let arr = []
},

遍历获取到的对象

js
productCallback(row) {
  let arr = []
  for (const value of Object.entries(row)) {
    console.log(value)
  }
},

打印出来的结果如下所示:

结果

因此可以通过展开运算符分别获取 keyvalue ,上方代码可以改为以下形式:

js
productCallback(row) {
  let arr = []
  for (const [k, v] of Object.entries(row)) {
  }
},

注意:

  1. for of 遍历需要通过 Object.keys()Object.values()Object.entries() 这三个方法把数组或对象转为迭代对象,否则会报错。
  2. Object.entries() 遍历到的是一个数组,分别为每一项的键和值,因此可以用到数组的解构语法分别获取。

获取到的值转为数组遍历

js
productCallback(row) {
  let arr = []
  for (const value of Object.entries(row)) {
    console.log(value)
    v.split(',').forEach((item,index) => {

    })
  }
},

判断当前索引是否有值

通过 index 判断当前索引是否有值

  • 没有值,新建一个对象赋值,对象键为当前循环的 key ,值为当前数组遍历的 item
  • 有值,直接给该索引的对象赋值
js
productCallback(row) {
  let arr = []
  for (const value of Object.entries(row)) {
    console.log(value)
    v.split(',').forEach((item,index) => {
        // 如果该索引没数值,则添加;有数值,则修改
        if(!arr[index]) {
		 let obj  = {}
          obj[k] = item
          arr.push(obj)
        } else {
          arr[index][k] = item
        }
    })
  }
},

解释:

当数组当前索引项有值时,获取到的是对应的值;没有值时,获取到的是 undefined ,因此可以通过 ! 运算符进行判断。

获取新值

到这里第一步完成了,但是需要考虑一个场景,用户选择了产品,填入数据,觉得选少了,想要多选几个,选择完毕后发现数据重新遍历渲染,之前填的数据都没了,这显然体验感很不好。

解决方案:每次用户重新选择后保留旧的值,追加新的值。

有了想法后该考虑如何实现,JavaScript 有一个内置对象 SetSet 方法可以去重,可以取交集、并集、差集。

思路

  1. 通过 Set 获取交集,该交集为用户上次已选择且当前继续保留的数据
  2. 通过 Set 获取差集,该差集为用户上次未选择,这次新增的数据
  3. 通过 concat 方法合并数组

实现

js
filterRows(rows = []) {
  // 传过来的是用户新获取的数组
  const newRowsId = rows.map(item => {
    return item.productId
  })
  
  // 这是保存用户上次选择的旧数组
  const oldRowsId = this.productList.map(item => {
    return item.productId
  })
  
  // 去重,转为set对象
  const newRowsIdToSet = new Set(newRowsId)
  const oldRowsIdToSet = new Set(oldRowsId)

  //取得交集,获取双方共同的数据,保证数据不被刷新
  const intersectRowsId = [...new Set([...newRowsIdToSet].filter(item => oldRowsIdToSet.has(item)))]
  const intersectRows = this.productList.filter(item => {
    return intersectRowsId.indexOf(item.productId) !== -1
  })

  // 取差集,获取新返回的本地数组没有的数据
  const differenceRowsId = [...new Set([...newRowsIdToSet].filter(item => !oldRowsIdToSet.has(item)))]
  const deIntersectRows = rows.filter(item => {
    return differenceRowsId.indexOf(item.productId) !== -1
  })

  return intersectRows.concat(deIntersectRows)
},

上一个函数调用获取

js
productCallback(row) {
  // ...
  // 长度大于0,说明前面已经保存过一次了,取差集;不大于0,说明第一次获取数据,直接保存即可。
  this.productList = this.productList.length > 0 ? this.filterRows(arr) : arr
},

Contributors

Yuan Tang