Various frameworks have the function of binding a list data to the DOM. For example, Angular will use ng-repeat to bind. What about Polymers? In fact, this level of functionality is an extension of the framework, and Angular’s ng-repeat is just a Directive. Polymer's dom-repeat is also of this level.
In Polymer, everything is a Directive concept. dom-module is used to define modules and is itself a Directive. The same goes for dom-repeat, but it is not a tag, but a Directive based on the template tag. We can use it like this:
Run
<script> var Polymer = { dom: 'shadow' }; </script> <base href="http://www.web-tinker.com/share/" /> <link rel="import" href="polymer/polymer.html" /> <dom-module id="demo-test"> <template> <ul> <template is="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>
The above code sets the is attribute of a template element to dom-repeat, so the contents of the template element are looped. This loop iterates based on the items attribute provided on the template element. Note that items must be an array. Although it may be a little inconvenient to use, I think this restriction is a very good practice. It avoids various problems caused by using for-in to traverse like Angular.
For each item of items, its index and value will be put into the two attributes index and item for use by the template in the template, so the above example outputs the given index and value.
However, Polymer's data update is not based on dirty data comparison, so dynamic update of data may be a bit troublesome. For example, if we have a button, if we want to add an item every time we click it, we should write it like this
Run
<script> var Polymer = { dom: 'shadow' }; </script> <base href="http://www.web-tinker.com/share/" /> <link rel="import" href="polymer/polymer.html" /> <dom-module id="demo-test"> <template> <input placeholder="请输入内容" value="{{value::input}}" /> <button on-click="append">添加一项</button> <ul> <template is="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>
We said before that Polymer will set the data that needs to be monitored for changes as an accessor property, but if you change the elements of the array, there is actually no change to the array itself. When we assign an array to VM, we actually copy the elements instead of throwing the array object there. In other words, this array object is not a direct reference to the VM. Operating this array object cannot affect the VM, so pushing the array directly is just a push to the data.
Although the push method of the array itself cannot operate the VM, Polymer itself also provides some methods for directly operating the VM. For example, this.push in the above example is provided by Polymer. Its operation template is not an object, but an access path on the VM (for example, the first parameter 'data' of push in the above example is the data access path in the VM).
In addition to push, there are also pop, shift and other operations similar to native methods (but please note that they are not element methods). Although it is indeed inconvenient to operate, it is not to the point of nausea. Anyway, I can barely accept it.