获取Vue组件中嵌套子项的状态

时间:2018-07-20 07:55:56

标签: javascript vue.js vue-component

我是使用VueJS和组件的新手,并且正在为不限级别的项目构建嵌套清单。

嵌套列表将可折叠,因此我想在每个列表的父级上显示状态。如果所有孩子(和儿童孩子等)都选中,则为绿色;如果仅选中其中一些,则为黄色。

我很难弄清楚如何在Vue中检查此内容,而没有每次循环遍历每个项目的常规javascript解决方案。我觉得必须有一个更清洁,更省力的解决方案。

在下面的代码片段中,您可以看到我在组件上使用的是“ childstatus”方法,以检查第一组子级上的状态,但这并没有完全消失。在示例中,您将看到Subitem 1-3-1被选中,Subitem 1-3为黄色,我也希望Item 1也为黄色。列表中的项目可以移动,也可以添加新项目,因此,我希望此操作尽可能自动进行,而不必每次都遍历所有项目,因为这些列表可能会变得很长很深。

Vue.component('checkin-list', {
  template: `
       <draggable :element="'ul'" class="checkin__list" :list="checklist" :options="{group:{ name: 'dragger' }}">
            <li v-for="(item,index) in checklist" :key="item.id">

                <div class="checkin__item" :status="childstatus(item)">               
                    <input type="checkbox" v-model="item.check">
                    {{ item.naam }}
                </div>

            	<checkin-list :checklist="item.checklist" :mode="mode" :type="type"></checkin-list>
            </li>
		</draggable>
	`,
  props: {
    checklist: Array
  },

  methods: {
    childstatus: (item) => {
      let info = {
        children: false,
        checked: false,
        children_all_checked: false,
        children_some_checked: false
      };

      if (item.check) {
        info.checked = true;
      }
      if (item.checklist.length) {
        info.children = true;

        if (item.checklist.some(x => x.check)) {
          info.children_some_checked = true;
          if (item.checklist.every(x => x.check)) {
            info.children_all_checked = true;
          }
        }
      }

      if (!info.children) {
        if (!info.checked) {
          return 0;
        } else {
          return 1;
        }
      } else {
        if (info.children_all_checked) {
          if (info.checked) {
            return 5;
          } else {
            return 4;
          }
        } else if (info.children_some_checked || info.checked) {
          return 3;
        } else {
          return 2;
        }
      }

    }
  }
});




var items = {
  "results": [{
    "id": 1,
    "naam": "Item 1",
    "check": 0,
    "checklist": [{
      "id": 2,
      "naam": "Subitem 1 - 1",
      "check": 0,
      "checklist": []
    }, {
      "id": 3,
      "naam": "Subitem 1 - 2",
      "check": 0,
      "checklist": []
    }, {
      "id": 4,
      "naam": "Subitem 1 - 3",
      "check": 0,
      "checklist": [{
        "id": 5,
        "naam": "Subitem 1 - 3 - 1",
        "check": 1,
        "checklist": []
      }]
    }, {
      "id": 6,
      "naam": "Subitem 1 - 4",
      "check": 0,
      "checklist": []
    }]
  }, {
    "id": 7,
    "naam": "Item 2",
    "check": 0,
    "checklist": []
  }]
}

new Vue({
  el: "#app",
  data: {
    checklist: items.results
  }
})
body {
  background: #fff;
  font-family: Helvetica;
}

#app {
  padding: 10px;
  transition: all 0.2s;
}
ul { list-style: none; }

li {
  margin: 8px 0;
}

.checkin__list {
  padding-left: 20px;
  padding-bottom: 10px;
}

.checkin__item[status="1"],
.checkin__item[status="5"] {
  background-color: #abeab4;
}


/* green */

.checkin__item[status="3"],
.checkin__item[status="4"] {
  background-color: #f6f5a7;
}


/* yellow */
<div id="app">

  <checkin-list :checklist="checklist"></checkin-list>

</div>


<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.6.0/Sortable.min.js"></script>
<script src="https://cdn.rawgit.com/David-Desmaisons/Vue.Draggable/master/dist/vuedraggable.js"></script>

或检查JSFiddle:https://jsfiddle.net/8b1yfj0x/16/

1 个答案:

答案 0 :(得分:0)

虽然我没有按照最初的想法解决问题,但确实创建了解决方案。

我重写了该函数,以便在(嵌套的)子级中始终可以使用1级父级的id。当孩子更新时,它会在提及该ID时发出事件。然后,在主要元素上,Vue方法从该id开始,并沿其所有子级向下确定状态。当任何变化时,我只是再次发出该变化。