如何使用聚合物1.0中的对象而不是数组使用dom-repeat?
迭代数组myarray=[1, 2, 3]
工作原理是这样的:
<template is="dom-repeat" items="[[myarray]]"> <span>[[item]]</span> </template>
我如何迭代一个对象myobject = {a:1, b:2, c:3}
?
这是一个完整的实现:
<test-element obj='{"a": 1, "b": 2, "c": 3}'></test-element> <dom-module id="test-element"> <template> <template is="dom-repeat" items="{{_toArray(obj)}}"> name: <span>{{item.name}}</span> <br> value: <span>{{item.value}}</span> <br> <hr> </template> </template> <script> Polymer({ properties: { obj: Object }, _toArray: function(obj) { return Object.keys(obj).map(function(key) { return { name: key, value: obj[key] }; }); } }); </script> </dom-module>
我面临同样的问题,但是我的用例要求更高一些:我需要双向深层次的绑定。 另外,我不能在每次更改时重写整个树。
由于我没有find解决办法,聚合物小组似乎慢慢地在这个问题上,我暂时做了一些事情。 它是用ES2015编写的,但是把它翻译成vanilla ES5应该很简单。 无论如何,在Chrome中运行。 或把它扔在bable上。 本页详细介绍如何。 本帖的目的是要点:
vulcanize element.html --inline-script --inline-css | \ crisper -h element.v.html -j element.js; babel element.js -o element.js
所以在这里我们去:
<link rel="import" href="../../bower_components/polymer/polymer.html"> <dom-module id="my-objarray"> <script> (function() { 'use strict'; class Objarray { beforeRegister() { this.is = 'my-objarray'; this.properties = { array:{ notify:true, type:Array, value:function() {return new Array();} }, object:{ notify:true, type:Object } }; this.observers = ['_onArray(array.*)', '_onObject(object.*)']; } _onObject(change) { if(this._setting) return; if(change.path == "object") this._rewriteArray(); else this._writeElement(change); } _rewriteArray() { this.splice("array", 0, this.array.length); for(let i in this.object) { this.push("array", {key:i, value:this.object[i]}); } } _writeElement(change) { const path = change.path.match(/^object\.([^\.]+)(.*)$/); const key = path[1]; const objectPath = "object." + key + (path[2] || ""); const id = this._getId(key); const arrayPath = "array." + id + ".value" + (path[2] || ""); this.set(arrayPath, this.get(objectPath)); } _getId(key) { const collection = Polymer.Collection.get(this.array); for(const element of this.array) { if((element && element.key) === key) { return collection.getKey(element); } } } _onArray(change) { let path = change.path.match(/^array\.(#\d+)\.([^\.]+)(\.|$)/); if(!path) return; let id = path[1], field = path[2]; if(field == "key") throw new Error("my-objarray: Must not change key!"); if(field != "value") throw new Error("my-objarray: Only change inside value!"); this._setting = true; this.set(this._getPath(change, id), change.value); delete this._setting; } _getPath(change, id) { let collection = Polymer.Collection.get(change.base); let index = change.base.indexOf(collection.getItem(id)); let key = change.base[index].key; return change.path.replace("array." + id + ".value", "object." + key); } } Polymer(Objarray); })(); </script> </dom-module>
用法:
<dom-module id="my-objarray-test"> <template strip-whitespace> <my-objarray object="{{items}}" array="{{array}}"></my-objarray> <template is="dom-repeat" items="{{array}}"> <div> <label>{{item.key}}:</label> <input type="number" value="{{item.value.data::input}}"> </div> </template> </template> <script> (function() { 'use strict'; class ObjarrayTest { beforeRegister() { this.is = 'my-repeat-test'; this.properties = { items:{ notify:true, type:Object, value:function() {return new Object();} } }; this.observers = ['_onItems(items.*)']; } ready() { console.log("my-repeat-test.ready"); this.items = {a:{data:1}, b:{data:2}}; } _onItems(change) {console.log("test._onItems", change.path);} } Polymer(ObjarrayTest); })(); </script> </dom-module>
希望能帮助别人。 可推出的聚合物现在得到像明天的function:-)
我一直在使用Object.keys(obj).map(function(prop){return {id:prop, val:obj[prop]}})
你需要把这个对象变成一个有意义的数组,以便能够用dom-repeat
迭代它。
我用初始值创build了一个myObj
属性。 然后我创build了一个名为myObjAsArray
的属性,它是一个空数组。 在ready
callback函数中,当本地dom准备就绪时,我将遍历myObj
所有属性,并将它们添加到myObjAsArray
(请参阅这里了解如何遍历对象属性)。 然后你可以用dom-repeat
迭代这个数组。
<link rel="import" href="bower_components/polymer/polymer.html"> <dom-module id="test-element"> <style> </style> <template> <template is="dom-repeat" items="{{myObjAsArray}}"> name: <span>{{item.name}}</span> value: <span>{{item.value}}</span> </template> </template> </dom-module> <script> Polymer({ is: "test-element", properties: { myObj: { type: Object, value: function () { return { a: 1, b: 2, c: 3 }; } }, myObjAsArray: { type: Array, value: function () { return []; } } }, attached: function () { var propArray = []; for (var prop in this.myObj) { if (this.myObj.hasOwnProperty(prop)) { propArray.push({name: prop, value: this.myObj[prop]}); } } this.myObjAsArray = propArray; } }); </script>
重新考虑这个问题是为了解释其他人提到的问题。 这与所有浏览器兼容,并使用hasOwnProperty
。
<template is="dom-repeat" items="[[_toArray(obj)]]"> key: [[item.key]] val: [[item.val]] </template>
…
_toArray: function(obj, deep) { var array = []; for (var key in obj) { if (deep || obj.hasOwnProperty(key)) { array.push({ key: key, val: obj[key] }); } } return array; }
Object.keys()在IE中似乎不起作用。 所以修改实现使用_.map来代替。
<test-element obj='{"a": 1, "b": 2, "c": 3}'></test-element> <dom-module id="test-element"> <template> <template is="dom-repeat" items="{{getKeyValue(obj)}}"> key: <span>{{item.key}}</span> <br> value: <span>{{item.value}}</span> <br> <hr> </template> </template> <script> Polymer({ properties: { obj: Object }, getKeyValue: function(obj) { return _.map(obj, function(value, key) { return { key: key, value: value }; }); } }); </script> </dom-module>