聚合物2中的递归和渲染

时间:2018-02-14 18:15:42

标签: javascript polymer polymer-2.x

当变量'works'设置为true(以铬为单位)时,以下代码按预期工作,但不是时。我想弄明白为什么。虽然我可以使用工作的,但我应该更好地理解为什么非工作的不起作用。为什么使用this.push一次推送一个数组项并使用this.set设置整个数组之间有什么区别?

'use strict'

var data = [{
  id: 1,
  children: [{
    id: 2
  }, {
    id: 3,
    children: [{
      id: 4
    }, {
      id: 5,
      children: [{
        id: 6
      }, {
        id: 7
      }]
    }, {
      id: 8
    }]
  }, {
    id: 9,
    children: [{
      id: 10,
      children: [{
        id: 11
      }, {
        id: 12
      }, {
        id: 13
      }]
    }, {
      id: 14
    }, {
      id: 15
    }]
  }]
}];

class Polymerology2Element extends Polymer.Element {
  static get is() {
    return 'polymerology2-element';
  }

  static get properties() {
    return {
      nodeData: {
        type: Array,
        value: [],
        notify: true
      },
      node: {
        type: null,
        value: null,
        notify: true
      }
    };
  }

  isOdd(num) {
    return num % 2;
  }


  addNodes() {

    var works = true;

    if (works) {
      if (this.node !== null) {
        var arr = [];
        for (var i = 0; this.node !== undefined &&
          this.node !== null && this.node.children !== undefined && i < this.node.children.length; i++) {

          arr.push(this.node.children[i]);
        }
        setTimeout(() => {
          this.set('nodeData', arr)
        }, 0);
      }
    } else {
      if (this.node !== null) {
        for (var i = 0; this.node !== undefined &&
          this.node !== null && this.node.children !== undefined && i < this.node.children.length; i++) {
          setTimeout(() => {
            this.push('nodeData', this.node.children[i])
          }, 0);
        }
      }
    }
  }

  constructor() {
    super();

    if (Polymerology2Element.instance === undefined) {
      this.nodeData = data;
      this.node = null;
      Polymerology2Element.instance = 0;
    } else
      Polymerology2Element.instance += 1;
    this.instance = Polymerology2Element.instance;
  }

  connectedCallback() {
    super.connectedCallback();
    this.addNodes();
  }
}

window.customElements.define(Polymerology2Element.is, Polymerology2Element);
:host {
  display: block;
}
<base href="https://polygit.org/polymer+polymer+v2.3.1/components/" />
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html" />

<polymerology2-element></polymerology2-element>

<dom-module id="polymerology2-element">
  <template>
    <ul>
      <template is="dom-repeat" items="[[nodeData]]" as="item">
        <template is="dom-if" if="{{isOdd(item.id)}}">
          <li>Instance: {{instance}}, Node: {{item.id}} (odd)</li>
          <polymerology2-element node="[[item]]"></polymerology2-element>
        </template>

        <template is="dom-if" if="{{!isOdd(item.id)}}">
          <li>Instance: {{instance}}, Node: {{item.id}} (even)</li>
          <polymerology2-element node="[[item]]"></polymerology2-element>
        </template>
      </template>
    </ul>
  </template>
</dom-module>

1 个答案:

答案 0 :(得分:0)

这与循环和变量环境如何工作有关 - 而不是与聚合物本身有关。

<强>为什么

观察两个选项之间的以下差异:

  • 在第一个选项中(在works循环中),setTimeOut在循环外被调用。
  • 但是在你的第二个选项(不起作用的选项)中,setTimeOut位于循环内部。 这意味着当您进行所有push次调用时(由于您选择了0超时,就在调用堆栈的末尾),您的for循环已经完成。 i已递增并等于this.node.children.length + 1。 (+ 1是因为在达到this.node.children.length后,由于i,您的i++将再次递增。这就是为什么你得不到你期望的东西:你实际上已经多次this.push('nodeData', this.node.children[ this.node.children.length + 1 ])

如何修复
我知道你已经有了一个工作选项,并没有真正寻找你的this.push选项的修复 - 但是如果你将来遇到类似的情况,通常可以做到这一点:你需要创建一个在setTimeOut周围关闭,以便在调用回调时记住i的值。

试试这个:

        for (var i = 0; /* ... your conditions */; i++) {
          (function(j) {
            setTimeout(() => {
             this.push('nodeData', this.node.children[j])
            }, 0);
          })(i);
        }