Skip to content

Kevin's Home

Polymer 2.0 文档笔记(7) Helper Element

Polymer3 min read

Polymer提供一系列的自定义元素来简化一些共有的数据绑定逻辑:

  • dom-repeat 遍历显示数组
  • array-selector 数组选择器
  • dom-if 条件显示
  • dom-bind 自动绑定

2.0 tip. The data binding helper elements are bundled in to the backward-compatible, polymer.html import. If you aren't using the legacy import, you'll need to import the helper elements you're using.

为了向前兼容,polymer.html引入了所有的helper元素,而2.0的polymer.Element则要按照需要一个个手动引入。

Template repeater (dom-repeat)

dom-repeat需要绑定一个数组,遍历显示里面元素,并为每个数组元素创建一个新的data scope,包括下面两个属性:

  • item 数组元素
  • index 元素下标

有两种用法:

  • 在Polymer element template内部,可以直接使用简写
  • 在Polymer element template外部,使用<dom-repeat>标签在这种情况下,还需要手动使用js给<dom-repeat>标签设置数据:

需要使用可被监听的手段去更改dom-repeat绑定的数组

Handling events in dom-repeat templates {#handling-events}

When handling events generated by a dom-repeat template instance, you frequently want to map the element firing the event to the model data that generated that item.

When you add a declarative event handler inside the <dom-repeat> template, the repeater adds a model property to each event sent to the listener. The model object contains the scope data used to generate the template instance, so the item data is model.item:

当你帮定义一个事件到dom-repeat的内部元素之后,事件参数e会有一个model项,代表着当前元素的data scope.

The model is an instance of TemplateInstance, which provides the Polymer data APIs: get, set, setProperties, notifyPath and the array manipulation methods. You can use these to manipulate the model, using paths relative to template instance.

model也是一个TemplateInstance的子类,提供了get,set,setProperties,notifyPath等data API

只有在dom-repeat里面绑定过的属性才会赋给model,如下面例子,将productId绑定到不可见的自定义属性上,以便将productId添加到model对象中。

Handling events outside the dom-repeat template.

The model property is not added for event listeners registered imperatively (using addEventListener), or listeners added to one of the dom-repeat template's parent nodes. In these cases, you can use the dom-repeat modelForElement method to retrieve the model data that generated a given element. (There are also corresponding itemForElement and indexForElement methods.) 外部如果使用标准的DOM APIaddEventListener来监听子元素的事件时,则事件参数里面没有e.model属性,可以使用下面几个函数手动获得:

  • dom-repeat.modelForElement
  • dom-repeat.itemForElement
  • dom-repeat.indexForElement

Filtering and sorting lists

To filter or sort the displayed items in your list, specify a filter or sort property on the dom-repeat (or both): 可以在dom-repeat上指定filtersort的方法。

默认,filtersort方法只在两种情况下被调用:

  1. 数组发生可被监控的变化(observable change)
  2. 两者方法被动态重现、改变

使用render方法强制filtersort方法重新执行。(见Forcing synchronous renders)

To re-run the filter or sort functions when certain sub-fields of items change, set the observe property to a space-separated list of item sub-fields that should cause the list to be re-filtered or re-sorted.

如果filter/sort是依据数组元素的某一个子属性来排序的,需要在dom-repeat标签上设置一个observe属性,将过滤或排序依据的子属性按照空格连接起来的字符设为它的值。 比如,下面这个例子,设置一个叫isEngineerfilter

在dom-repeat标签上设置过滤器所使用过的元素子属性type manager.type

修改第0个元素中的manager.type将会导致整个列表重新过滤

Dynamic sort and filter changes

observe属性并不能完全解决所有需求,也许filter/sort函数需要用到其他地方的变量,因此我们可以实现一个computed binding来动态返回一个filter/sort函数

Filtering on array index

Because of the way Polymer tracks arrays internally, the array index isn't passed to the filter function. Looking up the array index for an item is an O(n) operation. Doing so in a filter function could have significant performance impact.

不能获得数组索引,只能通过this.items获得原来数组,再通过indexOf方法获得索引,效率低下。 注意,filter/sort方法中,不是数组元素所创建的子data scope

Nesting dom-repeat templates {#nesting-templates}

When nesting multiple dom-repeat templates, you may want to access data from a parent scope. Inside a dom-repeat, you can access any properties available to the parent scope unless they're hidden by a property in the current scope. 比如类继承一样,子scope中可以取父scope的所有没有被覆盖的属性。

To access properties from nested dom-repeat templates, use the as attribute to assign a different name for the item property. Use the index-as attribute to assign a different name for the index property. 可以使用as标记来对默认的item来重命名 可以使用index-as标记来对默认的index来重命名

Forcing synchronous renders

默认的dom-repeat是异步执行的,但是可以调用render方法使之立即同步渲染。 此方法性能代价比较大,适用于下面几种情况:

  • 单元测试的时候保证检查之前所有的选项都被渲染完毕
  • 在要滚动到某一特定元素之前保证其已经渲染完毕
  • 当外部数据变化导致的sort/filter方法需要重新运行

注意: render方法只会更新模型数据的Observable change,如果要全局更新见下一节。

Forcing the template to update

强制刷新列表元素,像之前所说过的三种解决方案:

  • notifySplices,如果你知道数组的具体变更方式
  • 克隆数组,如果必要,可以深度克隆,性能不佳
  • 使用mutableData标签再this.notifyPath(items)

Improve performance for large lists

当列表数据量很大的时候,dom-repeat支持延迟加载。设置initialCount属性,可以启动chunked modedom-repeat首先会渲染initialCount个元素,然后按照一个animation framechunk的形式渲染其他元素,这样能够让UI在渲染的过程中处理用户的输入。可以查看renderedItemCount属性(只读)来获得当前已被渲染的元素总数。

dom-repeat adjusts the number of items rendered in each chunk to try and maintain a target framerate. You can further tune rendering by setting targetFramerate.

dom-repeat尝试去维护一个targetFramerate函数来调整每一个渲染的chunk里面的元素个数,具体:targetFramerate

Data bind an array selection (array-selector)

Keeping structured data in sync requires that Polymer understand the path associations of data being bound. The array-selector element ensures path linkage when selecting specific items from an array.

array-selector 可以选择数组里面的元素,并自动把选择出来的元素的路径跟这些元素的原来路径进行连接。(linkPaths)

  • items属性接收一个数组。
  • 两个常见API: select(item)\deselect(item)
  • 对于数组元素子属性的任何变化都会同步到items数组中(path已经link了)
  • multi属性可以开关多选

Conditional templates (dom-if)

dom-if 可以按条件来显示其中的内容。最开始的时候dom-if中没有元素,当把if属性设置为true时里面就会出现template中的的元素,当if属性再次变为false时,其内部元素默认不会被删除,而是直接隐藏。可以设置restamptrue来禁止这种隐藏行为。

dom-if一样,有两种方式来定义:

  • 在Polymer element template内部,使用简写方式

  • 在Polymer element template外部,使用<dom-if>标签

    这种情况需要手动设置dom-if的属性:

代码实例:

Conditional templates introduce some overhead, so they shouldn't be used for small UI elements that could be easily shown and hidden using CSS.

条件模板会引入一些开销,因此不适合一些可以直接设置CSS来控制显示和隐藏的小元素。 但是条件模板也适用于下面几种情况:

  • 懒惰加载
  • 节省大型复杂网站的内存消耗(restam=true会带来性能上的损失)

Auto-binding templates (dom-bind)

Polymer data binding is only available in templates that are managed by Polymer. So data binding works inside an element's DOM template (or inside a dom-repeat or dom-if template), but not for elements placed in the main document.

To use Polymer bindings without defining a new custom element, use the <dom-bind> element. This template immediately stamps the contents of its child templateinto the main document. Data bindings in an auto-binding template use the <dom-bind> element itself as the binding scope.

Polymer的数据绑定只能在template中,为了简化流程,使用自动绑定(<dom-bind>)能够在不定义新的自定义元素的前提下进行数据绑定。

注意:

  1. 自动绑定只能在Polymer element之外定义(因此只有一种定义方式)
  2. dom-bind也提供了一个render方法来进行强制同步刷新。
  3. dom-bind同样也用一个mutableData属性来开关脏检测机制。

dom-change event

When one of the template helper elements updates the DOM tree, it fires a dom-change event.

当任意一个template helper elements更新了DOM树时,它们都会触发一个dom-change事件。

In most cases, you should interact with the created DOM by changing the model data, not by interacting directly with the created nodes. For those cases where you need to access the nodes directly, you can use the dom-change event.

原则上,我们不应该直接与DOM进行交互,而应该修改对应的模型数据。如果的确需要这样做的话,可以监听这个的dom-change事件来完成。