首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嵌套递归模块

嵌套递归模块
EN

Stack Overflow用户
提问于 2018-09-26 09:51:05
回答 1查看 181关注 0票数 1

我正在做一个点击和删除功能--在页面上,模块是以递归的方式使用的,因此它有一个父和子模块。

我遇到了一个问题,如果用户开始选择孩子-然后选择父-我想取消选择孩子。虽然我不确定如何存储或监视为进行全局取消选举而选择的父/子项中的更改。

因此,用户已经选择了bacon3的子级。如果他们选择了父母--它需要取消选择孩子--但是我觉得我现在被锁在模块的范围里了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-30 23:50:07

我认为这个例子将帮助您https://canary.ember-twiddle.com/468a737efbbf447966dd83ac734f62ad?openFiles=utils.tree-helpers.js%2C

所以,这是一个有趣的问题。结果发现,它更多地是一个递归问题,而不是任何与成员、javascript或复选框行为有关的问题。

以下是我所拥有的(使用更新的语法等等)(如果您可以选择升级到3.4,您肯定应该--这是一个梦想)

代码语言:javascript
复制
// wrapping-component.js
import Component from '@ember/component';
import { action, computed } from '@ember-decorators/object';

import { check } from 'twiddle/utils/tree-helpers';

export default class extends Component {  
  options = [{
    id: 1,
    label: 'burger',
    checked: false,
    children: [{
        id: 3,
      label: 'tomato',
      checked: false
    }, {
        id: 4,
      label: 'lettus',
      checked: false    
    }, {
      id: 5,
      label: 'pickle',
      checked: false
    }]
  }, {
    id: 2,
    label: 'kebab',
    checked: false,
    children: [{
        id: 6,
      label: 'ketchup',
      checked: false
    }, {
      id: 7,
      label: 'chilli',
      checked: false
    }]
  }];

  @action
  toggleChecked(id) {
    const newTree = check(this.options, id);

    this.set('options', newTree);
  }
}

模板:

代码语言:javascript
复制
{{yield this.options (action this.toggleChecked)}}

以及使用情况:

代码语言:javascript
复制
// application.hbs
<WrappingComponent as |options toggle|>
  {{#each options as |item|}}

    <CheckboxGroup @item={{item}} @onClick={{toggle}} />

  {{/each}}
</WrappingComponent>

CheckboxGroup是一个只使用模板的组件:

代码语言:javascript
复制
// checkbox-group.hbs
<div class="checkboxhandler">
  <input 
    type="checkbox" 
    checked={{@item.checked}}
    onclick={{action @onClick @item.id}}
  >
  <label>{{@item.label}}</label>

  {{#if @item.children}}
    {{#each @item.children as |child|}}

       <CheckboxGroup @item={{child}} @onClick={{@onClick}} />

    {{/each}}
  {{/if}}
</div>

以及递归帮助程序(这很混乱,但我只是在做原型):

代码语言:javascript
复制
// utils/tree-helpers.js
const toggle = value => !value;
const disable = () => false;

// the roots / siblings are contained by arrays
export function check(tree, id, transform = toggle) {
  if (tree === undefined) return undefined;

  if (Array.isArray(tree)) {
    return selectOnlySubtree(tree, id, transform);  
  } 

  if (tree.id === id || id === 'all') {
    return checkNode(tree, id, transform);
  }

  if (tree.children) {
    return checkChildren(tree, id, transform);
  }

  return tree;
}

function selectOnlySubtree(tree, id, transform) {
  return tree.map(subTree => {
    const newTree = check(subTree, id, transform);

    if (!newTree.children || (transform !== disable && didChange(newTree, subTree))) {
      return newTree;
    } 

    return disableTree(subTree);
  });
}

function isTargetAtThisLevel(tree, id) {
  return tree.map(t => t.id).includes(id);
}

function checkNode(tree, id, transform) {
  return { 
    ...tree, 
    checked: transform(tree.checked),
    children: disableTree(tree.children)
  };
}

function disableTree(tree) {
  return check(tree, 'all', disable);
}

function checkChildren(tree, id, transform) {
    return { 
        ...tree, 
        checked: id === 'all' ? transform(tree.checked) : tree.checked,
    children: check(tree.children, id, transform) 
  };
}

export function didChange(treeA, treeB) {
  const rootsChanged = treeA.checked !== treeB.checked;

  if (rootsChanged) return true;

  if (treeA.children && treeB.children) {
    const compares = treeA.children.map((childA, index) => {
      return didChange(childA, treeB.children[index]);
    });

    const nothingChanged = compares.every(v => v === false);

    return !nothingChanged;
  }

  return false;
}

希望这能有所帮助。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52514840

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档