0

[9 月 24 日更新]

当我修改我的 $watched 对象数组时,我正在尝试使用 ngReact 而不是 ngRepeat 来提高性能。

对于控制器中包含的每个对象(地图标记),我想创建一个<button>带有marker.titleas 文本的 ,。为此,我创建了一个 $watches 标记数组的 React 组件。这样的 a 包含一个列表,每个标记一个。我认为只有当我修改标记列表,然后是按钮列表时,组件才会发生变化。然而,这种情况并非如此。

[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

似乎<button>由 React 组件创建的列表结果总是不同的,即使是由相同的对象创建的。

现在奇怪的部分.. 实际上,我使用 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 中有 2 个数组。temp_list 用于临时将所有标记一一推送。m_list 由 react 组件 $watched。
  • 有一个 MapBox 指令及其控制器。对于添加到地图的每个标记,它将被推送到 temp_list 中。
  • 一旦所有标记都已加载并且 temp_list 完成,它会被克隆到 m_list,因此可以更新 react 组件。

谢谢你

4

1 回答 1

0

我找到了解决办法!这个问题在某种程度上与地图的使用有关。在监视的数组中,我没有添加 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 项目论坛上的海报

于 2015-10-02T08:30:34.547 回答