根据来自不同对象数组的属性和值过滤对象数组

时间:2019-09-08 19:34:46

标签: javascript arrays vue.js filter

我有两组数组,一组用于表的标题(列),另一组用于表的行。

const headers = [
  {
    text: 'Dessert (100g serving)',
    align: 'left',
    sortable: false,
    value: 'name',
    visible: true
  },
  { text: 'Calories', value: 'calories', visible: true },
  { text: 'Fat (g)', value: 'fat', visible: true },
  { text: 'Carbs (g)', value: 'carbs', visible: true },
  { text: 'Protein (g)', value: 'protein', visible: true },
  { text: 'Iron (%)', value: 'iron', visible: true }
]

const desserts = [
  {
    name: 'Frozen Yogurt',
    calories: 159,
    fat: 6.0,
    carbs: 24,
    protein: 4.0,
    iron: '1%'
  },
  {
    name: 'Ice cream sandwich',
    calories: 237,
    fat: 9.0,
    carbs: 37,
    protein: 4.3,
    iron: '1%'
  },
  {
    name: 'Eclair',
    calories: 262,
    fat: 16.0,
    carbs: 23,
    protein: 6.0,
    iron: '7%'
  },
  {
    name: 'Cupcake',
    calories: 305,
    fat: 3.7,
    carbs: 67,
    protein: 4.3,
    iron: '8%'
  }
]

我要实现的目标是使用户能够确定他们希望在表中查看数据的哪些列。

我正在使用Vue.js,因此我一直试图列出一组复选框,每个复选框都是v-bind作为headers集合的标题。

我正在使用以下方法进行操作:

computed: {
  filteredHeaders () {
    return this.headers.filter(header => header.visible)
  }
}

这可以按预期工作,哎呀!表格列标题根据复选框所选择的列而变化。

我坚持的一点是试图根据选定的列(或desserts)来过滤行数据(或filteredHeaders)。

我尝试了以下操作:

computed: {
  ...
  filteredItems () {
    return this.desserts.filter(dessert => {
      return this.filteredHeaders.some(header => {
        return Object.keys(header).some(prop => {
          return dessert[prop] != header[prop] && header.visible
        })
      })
    })
  }
}

即使没有引发任何错误,filteredItems的结果仍然是原始desserts的结果以及应排除的属性(当visible设置为{{1 }}旁边的复选框仍在显示。

我确定我已经关闭了,但是关闭并不能使我得到那支雪茄(俗话说)!

1 个答案:

答案 0 :(得分:1)

此方法应该可以大致满足您的需求:

const headers = [{
    text: "Dessert (100g serving)",
    align: "left",
    sortable: false,
    value: "name",
    visible: true
  },
  {
    text: "Calories",
    value: "calories",
    visible: true
  },
  {
    text: "Fat (g)",
    value: "fat",
    visible: true
  },
  {
    text: "Carbs (g)",
    value: "carbs",
    visible: true
  },
  {
    text: "Protein (g)",
    value: "protein",
    visible: true
  },
  {
    text: "Iron (%)",
    value: "iron",
    visible: true
  }
];

const desserts = [{
    name: "Frozen Yogurt",
    calories: 159,
    fat: 6.0,
    carbs: 24,
    protein: 4.0,
    iron: "1%"
  },
  {
    name: "Ice cream sandwich",
    calories: 237,
    fat: 9.0,
    carbs: 37,
    protein: 4.3,
    iron: "1%"
  },
  {
    name: "Eclair",
    calories: 262,
    fat: 16.0,
    carbs: 23,
    protein: 6.0,
    iron: "7%"
  },
  {
    name: "Cupcake",
    calories: 305,
    fat: 3.7,
    carbs: 67,
    protein: 4.3,
    iron: "8%"
  }
];

const filterRows = (rows, headers) => {
  // Map over the full list of rows to filter down
  return rows.map(row => {
    // Create a new row to return to avoid mutating
    const filteredRow = {};
    // Loop through each header and copy the row value corresponding to that header value
    headers.forEach(header => {
      filteredRow[header.value] = row[header.value];
    });
    // Return the copied and filtered row
    return filteredRow;
  });
};

console.log(filterRows(desserts, headers));
console.log(filterRows(desserts, [{
  text: "Iron (%)",
  value: "iron",
  visible: true
}]));