JavaScript的Polymer框架中dom-repeat与VM的相关操作
各种框架都有把一个列表数据绑定到DOM上的功能,比如Angular会用ng-repeat来绑定。那么Polymer呢?其实这个级别的功能属于框架的扩展功能了,Angular的ng-repeat也只是个Directive而已。Polymer的dom-repeat也是这个级别的东西。
在Polymer中,一切都是Directive的概念。dom-module用于定义模块,它本身也是一个Directive。dom-repeat也是,但它不是一个标签,而是一个基于template标签的Directive。我们可以这样使用它:
运行
<script>varPolymer={dom:'shadow'};</script> <basehref="http://www.web-tinker.com/share/"/> <linkrel="import"href="polymer/polymer.html"/> <dom-moduleid="demo-test"> <template> <ul> <templateis="dom-repeat"items="[[data]]"> <li> 第<strong>[[index]]</strong>项, 值为<strong>[[item]]</strong> </li> </template> </ul> </template> <script> Polymer({ is:'demo-test', properties:{ data:{ type:Array, value:['a','b','c','d'] } } }); </script> </dom-module> <demo-test></demo-test>
上面的代码对某个template元素设置is属性为dom-repeat,于是这个template元素内的东西就被循环了。这个循环根据在template元素上提供的items属性来遍历。注意items必须是数组,虽然用起来可能有点不太方便,但我觉得这个限制是一个非常好的做法。避免了像Angular那样使用for-in去遍历导致的各种问题。
items的每一项,其索引和值会被放入index和item这两个属性中供template内的模板使用,于是上面的例子就输出了给定的索引和值。
然而Polymer的数据更新并不是基于脏数据比对,所以数据的动态更新可能就有点麻烦。比如我们有一个按钮,每次点击要增加一项的话应该这么写
运行
<script>varPolymer={dom:'shadow'};</script> <basehref="http://www.web-tinker.com/share/"/> <linkrel="import"href="polymer/polymer.html"/> <dom-moduleid="demo-test"> <template> <inputplaceholder="请输入内容"value="{{value::input}}"/> <buttonon-click="append">添加一项</button> <ul> <templateis="dom-repeat"items="[[data]]"> <li> 第<strong>[[index]]</strong>项, 值为<strong>[[item]]</strong> </li> </template> </ul> </template> <script> Polymer({ is:'demo-test', properties:{ data:{ type:Array, value:['a','b','c','d'] } }, append:function(){ //data.push(this.value);//这么写是不行的 this.push('data',this.value) } }); </script> </dom-module> <demo-test></demo-test>
之前我们说过,Polymer会将需要监控变化的数据作为一个访问器属性来设置,但如果改变数组的元素,实际上并没有对数组本身有任何改动。当我们把一个数组赋值给VM时实际上是把元素复制过去,而不是把数组对象丢过去。也就是说,这个数组对象并不直接是VM的引用,操作这个数组对象是无法影响VM的,所以直接对数组做push只是对数据的push。
虽然数组自己的push方法无法操作VM,但Polymer自己也提供了一些直接操作VM的方法,比如上面例子中的this.push就是Polymer提供的。它的操作模板不是一个对象,而是VM上的一个访问路径(比如上面例子中push的第一个参数'data'就是VM中data访问路径)。
除了push之外还有pop、shift等一些类似原生方法的操作(但要注意他们不是元素方法)。虽然操作起来确实不太方便,但也不至于到恶心的程度,反正我是勉强能接受的。