[9月24日更新]
我试图使用ngReact而不是ngRepeat来提高性能,当我修改我的$watched对象数组。
对于控制器中包含的每个对象(一个地图标记),我想创建一个<button>
,其中marker.title
为文本。为此,我创建了一个React组件来$监视一组标记。这样的目录包含一个列表,每个标记对应一个。我假定组件只有在修改标记列表和按钮列表时才会导致改变。然而,事实并非如此。
[TypeError]: Illegal invocation
at isArrayLike (angular.js:274)
at forEach (angular.js:328)
at copy (angular.js:886)
[Error]: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.4.0-rc.0/$rootScope/infdig?p0=10&p1=%5B%5D
at REGEX_STRING_REGEXP (angular.js:68)
at Scope.parent.$get.Scope.$digest (angular.js:15340)
at Scope.parent.$get.Scope.$apply (angular.js:15570)
at (index):95
似乎由React组件创建的<button>
列表结果总是不同的,即使由相同的对象制作。
现在奇怪的是…实际上,我使用Json对象向地图添加标记。当我添加一个Json对象时,映射创建一个Marker
对象,而不是jsonable,因为它具有圆形结构。我将这个Marker
对象添加到我的$watched数组中,以创建相对的<button>
…也许这就是illegal isArrayLike()
错误的原因?
这是我的React组件(在我的文章末尾,有JSfiddle链接)
HTML <!-- m_list is an attribute of $rootScope -->
<poi-list list="m_list" />
JS
.value( "PoiList", React.createClass( {
propTypes : {
list: React.PropTypes.object.isRequired
},
render: function()
{
var markers = this.props.list.map( function( marker, i )
{//for each marker, create a button
return React.DOM.button( {
className:'btn btn-default'
}, marker.title
) ;
} );
return React.DOM.div({}, markers);
}
}))
.directive( 'poiList', function( reactDirective ) {
return reactDirective( 'PoiList' );
} );
这是我的问题的JSFiddle。简要说明:
- $rootScope中有两个数组。Temp_list用于一个接一个地临时推入所有标记。m_list由react组件$监视。
- 有一个MapBox指令和它的控制器。对于添加到地图中的每个标记,它将被推送到temp_list中。
- 一旦所有的标记都被加载并且temp_list完成,它就被克隆到m_list,这样react组件就可以被更新了。
谢谢
我找到解决办法了!这个问题在某种程度上与地图的使用有关。在观察数组中,我没有添加Json标记,但我添加了由MapBox创建的对象标记。
map.featureLayer.setGeoJSON(json_markers_list); // I pass an array of Json markers
map.featureLayer.on('layeradd', function(e)
{
var marker = e.layer; // marker is anymore a json obj
ctrl.pushMarker(marker); // marker now has a cyclic structure
});
MapBox创建的对象标记具有循环结构。由于这个原因,React无法知道自上次检查以来旧的$watched数组是否发生了变化,因为当循环结构存在时,它无法执行isArrayLike()
。因此,它抛出一个错误(在任何浏览器中都不同),并认为数组总是被更改,生成$digest无限迭代。
我的解决方案是使用一个数组和一个映射。数组是$watched,其中包含我需要在按钮
中显示的信息{'title': 'marker title', 'id':00001}
地图包含真正的标记对象
{'00001' : {markerObj}}
,这是一个工作的JSFiddle !点击一个按钮,标记对象将被选中。
这个问题和解决方案也是在官方ng-react项目论坛上的海报