Vue 中带有复选框的嵌套表

问题描述 投票:0回答:1

所以我有一个嵌套表格,我希望表格标题中的复选框自动检查其子项中的所有复选框

这是我的 vue 代码:

// TEMPLATE
<table class="table">
  <thead>
    <tr>
      <th><input type="checkbox" value="row-all" v-model="selectAllCheckbox"></th> --> CHECKBOX IN HEADER OF PARENT TABLE
      ...
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><input type="checkbox" :value="`row-${row.id}`" v-model="checkedRows"></td> --> CHECKBOX IN BODY OF PARENT TABLE
      ...
    </tr>
    <tr>
      <table>
        <thead>
          <tr>
            <th><input type="checkbox" :value="`child-${row.id}`" v-model="selectAllCheckbox"></th> --> CHECKBOX IN HEADER OF CHILD TABLE
            ...
          </tr>
        </thead>
        <tbody>
          <tr>
            <td><input type="checkbox" :value="`child-${row.id}-row-${index}`" v-model="checkedRows"></td> --> CHECKBOX IN BODY OF CHILD TABLE
          </tr>
        </tbody>
      </table>
    </tr>
  </tbody>
</table>
// SCRIPT
const selectAllCheckbox = ref(new Set())
const checkedRows = ref(new Set())

watch(() => selectAllCheckbox.value, () => {
  if (selectAllCheckbox.value.has('row-all')) {
    for (const key in shownData.value) {
      checkedRows.value.add(`row-${shownData.value[key].id}`)
    }
  } else {
    for (const key in shownData.value) {
      checkedRows.value.delete(`row-${shownData.value[key].id}`)
    }
  }
  for (const key in shownData.value) {
    if (selectAllCheckbox.value.has(`child-${shownData.value[key].id}`)) {
      for (let index = 0; index < shownData.value[key].product_entries.length; index++) {
        checkedRows.value.add(`child-${shownData.value[key].id}-row-${index}`)
      }
    } else {
      for (let index = 0; index < shownData.value[key].product_entries.length; index++) {
        checkedRows.value.delete(`child-${shownData.value[key].id}-row-${index}`)
      }
    }
  }
})
watch(() => checkedRows.value, () => {
  let condition = true
  for (const key in shownData.value) {
    if (!checkedRows.value.has(`row-${shownData.value[key].id}`)) {
      condition = false
    }
  }
  if (condition) {
    selectAllCheckbox.value.add('row-all')
  } else {
    selectAllCheckbox.value.delete('row-all')
  }

  for (const key in shownData.value) {
    condition = true
    for (let index = 0; index < shownData.value[key].product_entries.length; index++) {
      if (!checkedRows.value.has(`child-${shownData.value[key].id}-row-${index}`)) {
        condition = false
      }
    }
    if (condition && shownData.value[key].product_entries.length > 0) {
      selectAllCheckbox.value.add(`child-${shownData.value[key].id}`)
    } else {
      selectAllCheckbox.value.delete(`child-${shownData.value[key].id}`)
    }
  }
})

我的主要问题是关于复选框。现在上面的代码工作正常,我的问题是:

  1. 如你所见,我在 watch 函数中放了大概一百多个循环,这样可以吗?我的意思是,应用程序会很慢吗?
  2. 如果上面的答案是肯定的,那么我该如何解决这个问题呢?有没有例子可以解决这个问题?
javascript checkbox vuejs3 v-model
1个回答
0
投票

您可以使用

:checked
@input
的组合:

VUE SFC 游乐场

<script setup>
import { reactive, computed } from 'vue'
const props = defineProps({items:Array});
const selectedRows = reactive(new Set);


const allSelected = computed({
  get(){ return selectedRows.size === props.items.length; },
  set(val){
    val ? props.items.forEach(item => selectedRows.add(item.id)) : selectedRows.clear();
  }
});



</script>

<template>
  <table>
    <thead>
      <tr><td><input type="checkbox" v-model="allSelected"></td></tr>
    </thead>
    <tbody v-for="item in items">
      <tr><td><input type="checkbox" :checked="selectedRows.has(item.id)" 
      @input="selectedRows[selectedRows.has(item.id) ? 'delete' : 'add'](item.id)"/></td><td>{{ item.title }}</td></tr>
      <tr><td colspan="2" style="padding-left:32px"><table-select v-if=item.children :items="item.children"/></td></tr>
    </tbody>
  </table>
</template>
© www.soinside.com 2019 - 2024. All rights reserved.