树节点。子节点快速向上查找父节点

例如:

一个具有复选框的树,点击其中一个子节点时, 让父节点做出响应(如果子节点全部选中,则父节点选中),当然了,父节点选中后,祖父节点也要做出响应。

以上的算法,我是采用递归的方法,能出来但是很卡,使用现成的框架,如ElementUI则不会卡, 请问,这种是如何优化的,思路在哪里,请指教。

阅读 4.3k
2 个回答

elementUI 是开源的,源码可以看

那就瞅瞅递归的优化?尾递归?

最好还是把你的代码放出来,看看有没有多次调用的情况。

对了,有可能不是js卡,而是渲染卡。可以打打时间,或者不渲染在页面上试试

看check函数即可
其他是生成节点的

var o = [{
  check: false,
  items: [{
    check: false
  }, {
      check: false,
      items: [{
          check: false
      }, {
          check: false
      }, {
          check: false
      }]      
  }, {
      check: false,
      items: [{
          check: false
      }, {
          check: false
      }, {
          check: false
      }]      
  }]
}];

function getDom (o, n) {
    var par = document.createElement("div"),
        label = document.createElement('label'),
        check = document.createElement("input");


    check.type = 'checkbox';
    check.name = o.name;
    check.id = o.name;
    check.value = o.check;

    par.appendChild(check);

    label.innerText = o.name;
    label.setAttribute('for', o.name);

    par.appendChild(label);

    par.style = `margin-left: ${20 * n}px;`

    return par;
}

let map = new Map();

function createCheckBox(o) {
    var base = 97,
        box = document.createDocumentFragment(),
        pars = [],
        arr = [];
    function createCheck (o, n = 0) {
        var k = String.fromCharCode(base + n);
        if (o.forEach) {
            o.forEach(c => createCheck(c, n));
            return;
        }
        arr[n] = arr[n] || 0;
        par = pars[n - 1];
        o.name = k + '_' + (arr[n]++);
        o.id = o.name;
        map.set(o.name, o);

        if (par) {
            o.par = par.name;
            par.ic = par.ic || 0;
            par.ic += (o.check ? 1 : 0);
        }

        box.appendChild(getDom(o, n));

        if (o.items) {
            pars[n] = o;
            o.il = o.items.length;
            createCheck(o.items, n + 1);
        }
    }
    createCheck(o);
    document.body.appendChild(box);
}

createCheckBox(o);

function isCheck (id) {
    return $('#' + id)[0].checked;
}

function check (id) {
    let par = map.get(id).par;

    if (par) {
        par = map.get(par);
        par.ic = par.ic + (isCheck(id) ? 1 : -1);
        let pic = isCheck(par.id);

        if (par.ic !== par.il) {
            $('#' + par.id).prop('checked', false)
            if (pic) {
                check(par.id);
            }
        } else {
            $('#' + par.id).prop('checked', true)
            if (!pic) {
                check(par.id);
            }
        }
    }
}

$('input').on('change', function (e) {
    var id = $(this).attr('id');

    check(id);
})
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题