角度性能和与深度嵌套集合的数据绑定

角度性能和与深度嵌套集合的数据绑定

问题描述:

我正在使用chrome.bookmarks API以角度为Chrome创建书签管理器。角度性能和与深度嵌套集合的数据绑定

对于我的概念验证,我的书签页是我的所有书签的单个列表。我使用2个指令,两个遍历整个书签集合,一个collection directive和一个member directive。我遇到性能问题,我正在寻找方向。

tl; dr: 模型更改将永久更新我的观点,我做错了什么,以及我该如何做得更好?

下面是相关代码:

app.controller('bookmarksController', ['$scope', 'ChromeBookmarks', function($scope, chromeBookmarks) { 
    chromeBookmarks.getBookmarks().then(function(bookmarkTree) { 
    $scope.bookmarks = bookmarkTree; 
    }); 
}); 

的index.html

<div ng-controller="bookmarkController"> 
    <collection collection="bookmarks"></collection> 
</div> 

collection.js

app.directive('collection', function($compile) { 
    return { 
    restrict: 'E', 
    scope: { 
     collection: '=', 
    }, 
    templateUrl: 'collection.html', 
    }; 
}); 

collection.html

<ul> 
    <member ng-repeat="member in collection" member="member"></member> 
</ul> 

member.js

app.directive('member', ['$compile', function($compile) { 
    return { 
    restrict: 'E', 
    scope: { 
     member: '=', 
    }, 
    templateUrl: 'member.html', 
    link: function(scope, element, attrs) { 
     if (scope.member.children) { 
     var collectionTemplate = '<collection collection="member.children"></collection>'; 
     var collection = angular.element(collectionTemplate); 
     element.append(collection); 
     $compile(collection)(scope); 
     }  
    } 
    }; 
}]); 

member.html

<li> 
    <bookmark ng-if="member.url" node="member"></bookmark> 
    <folder ng-if="!member.url" node="member"></folder> 
</li> 

bookmark.js

app.directive('bookmark', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     node: '='   
    }, 
    templateUrl: 'bookmark.html' 
    }; 
}); 

bookmark.html

<div> 
    {{ node.title }} <button ng-click="open()">Live Site</button> 
</div> 

folder.js

app.directive('folder', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     node: '=' 
    }, 
    templateUrl: 'folder.html' 
    }; 
}); 

folder.html

<div> {{ node.title }} </div> 

正如你可以在我的控制器上面看到的,我只有附着范围一个模型:$scope.bookmarks。我只想加载一次这个变量。

页面加载完成后,我想将侦听器附加到chrome.bookmark events,这样如果书签发生更改,事件就会触发,我只需更改受影响的书签。

我目前使用的方法是使用一个函数,该函数将改变的书签和递归地移动通过$scope.bookmarks,并用从chrome.bookmarks API获得的更新版本替换书签的父项。该功能基本上是这样的:$scope.bookmarks[1].children[2] = updatedBookmark

我试着将侦听器添加到我的页面,但创建一个书签和随后更新的视图需要3秒(坏),如果我书签窗口中的每个选项卡,页面冻结(更糟糕)。我确实拥有大约2k个书签,但我仍然希望这能够超越这个水平。

我的理解是,糟糕的角度性能与拥有大量观察者有关,因为$digest周期变得太大。 这是您认为会导致我的表现问题吗?

如果我只是想修改$scope.bookmarks模型来触发更新视图,我真的需要多少个观察者?

我知道2路数据绑定是为了保持模型和视图同步,但我不禁想到,在我的情况下,我只想改变一点点数据(和变化基于书签API事件,不一定是用户输入),2路数据绑定似乎是错误的,尤其是因为$digest循环似乎检查了太多的数据。

但是后来我确实需要视图来正确镜像模型数据。 如果我摆脱了双向数据绑定,并且使用ngOnce进行一次绑定,我的模型的更改是否可以被渲染?

我刚刚遇到了角度的自然局限性,需要使用不同的框架?

Angular无法处理超过2000个手表,有些浏览器可以做得更多,但这是一个不错的上限。有两种可能性进行缓慢更新:

1)您正在使用Angular生命周期调用的API?如果是这样,请确保您执行一个作用域$ apply()。 2)你有太多的手表。有代码片段,你可以发现你在控制台中运行,会反弹手表的数量如果它们很高,那么考虑缓冲你的视图,以便只有你看到的是绑定的,github.com/EnzeyNet/VirtualScroll。

+0

我已经告诉视图使用范围进行更新$ apply,这就是触发摘要循环并放慢速度的一切 – markain 2014-11-25 17:54:39

+0

您注册了多少手表?在这里尝试一个脚本:http://*.com/questions/18499909/how-to-count-total-number-of-watches-on-a-page – Enzey 2014-11-25 20:16:27