Vuejs - v-bind.sync on resursive components (hierarchical list)

Vuejs - v-bind.sync on resursive components (hierarchical list)

我有一个分层列表组件,其中 child 项有复选框。复选框操作 (check/uncheck) 必须使 parent 组件与复选框的更改状态保持同步。我无法弄清楚如何递归地使用 v-bind.sync 来实现这一点。我的代码如下:

Menu.vue

此组件包含分层列表。 (仅包含相关代码)

  1. HierarchicalCheckboxList 是显示分层列表的组件
  2. 属性 'value' 保存 check/uncheck 值 (true/false)
  3. 属性 'children' 包含 child 列表项

How do I define the .sync attribute on HierarchicalCheckboxList and with what parameter?

<template>
<div>
    <HierarchicalCheckboxList
      v-for="link in links"
      @checked="primaryCheckChanged"
      :key="link.id"
      v-bind="link">
    </HierarchicalCheckboxList>
</div>
</template>
<script>
    import HierarchicalCheckboxList from 'components/HierarchicalCheckboxList'

    data () {
       return {
          links: [{
             id: 1,
             title: 'Home',
             caption: 'Feeds, Dashboard & more',
             icon: 'account_box',
             level: 0,
             children: [{
               id: 2,
               title: 'Feeds',
               icon: 'feeds',value: true,
               level: 1,
               children: [{
                  id: '3',
                  title: 'Dashboard',
                  icon: 'settings',
                  value: true,
                  level: 1
               }]
             }]
          }]
       }
    },
    methods: {
      primaryCheckChanged (d) {
        // A child's checked state is propogated till here
        console.log(d)
      }
    }
</script>

HierarchicalCheckboxList.vue

该组件递归调用自身:

<template>
  <div>
    <div v-if="children != undefined && children.length == 0">
      <!--/admin/user/user-->
      <q-item clickable v-ripple :inset-level="level" :to="goto">
        <q-item-section>
          {{title}}
        </q-item-section>
      </q-item>
    </div>
    <div v-else>
      <div v-if="children != undefined && children.length > 0">
        <!-- {{children}} -->
        <q-expansion-item
            expand-separator
            :icon="icon"
            :label="title"
            :caption="caption"
            :header-inset-level="level"
            default-closed>
            <template v-slot:header>
              <q-item-section>
                {{ title }}
              </q-item-section>
              <q-item-section side>
                <div class="row items-center">
                  <q-btn icon="add" dense flat color="secondary"></q-btn>
                </div>
              </q-item-section>
            </template>
          <HierarchicalCheckboxList
            v-for="child in children"
            :key="child.id"
            @checked="primaryCheckChanged"
            v-bind="child">
          </HierarchicalCheckboxList>
        </q-expansion-item>
      </div>
      <!-- to="/admin/user/user" -->
      <div v-else>
        <q-item clickable v-ripple :inset-level="level">
          <q-item-section>
            <q-checkbox :label="title" v-model="selection" />
          </q-item-section>
        </q-item>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'HierarchicalCheckboxList',
  props: {
    id: { type: String, required: true },
    title: { type: String, required: false },
    caption: { type: String, default: '' },
    icon: { type: String, default: '' },
    value: { type: Boolean, default: false },
    level: { type: Number, default: 0 },
    children: { type: Array }
  },
  data () {
    return {
      localValue: this.$props.value
    }
  },
  computed: {
    selection: {
      get: function () {
        return this.localValue
      },
      set: function (newvalue) {
        this.localValue = newvalue
        this.$emit('checked', this.localValue) 
        // or this.$emit('checked', {id: this.$props.id, value: this.localValue })
      }
    }
  },
  methods: {
    primaryCheckChanged (d) {
      this.$emit('checked', d)
    }
  }
}
</script>

目前有效的方法

作为 work-around,我能够通过 $emit('checked') 获得复选框状态,我用它来将其发送到下一个进程。但是 parent 的状态直到我从数据库中刷新它才更新。

如何使用 v-bind.sync 递归地更新 parent 组件的状态?

感谢任何帮助!!

UI

在我将代码从整个 2000 行代码分解为单独的 'trial-n-error' 20 行代码之后,我想出了如何去做,然后事情变得简单明了。

Menu.vue

HierarchicalCheckboxList 声明中父组件的一些更改: 注意 sync 属性

<HierarchicalCheckboxList
   v-for="child in children"
   :key="child.id"
   :u.sync="link.value"
   v-bind="child">
</HierarchicalCheckboxList>

HierarchicalCheckboxList.vue

更改子组件中的同一行代码(作为其递归)

   <HierarchicalCheckboxList
     v-for="child in children"
     :key="child.id"
     :u.sync="child.value"
     v-bind="child">
   </HierarchicalCheckboxList>

并且在计算集 属性 中,发出如下:

   this.$emit('update:u', this.localValue)

就是这样 - 父 n 个子组件现在保留在 snyc 中。