随着SPA应用程序的增长,Angular JS的一些事情变得不清楚。
假设我们有一个包含大量引用实体的RDBMS数据结构,如Country(id),State(id,countryId),City(id,stateId),Street(id,cityId)。
我们需要在一个视图中渲染大部分内容,就像递归分组的街道索引一样。我知道这不是那么实用的例子,特别是考虑到我们真正的应用程序实体有我们需要绑定的共同数据。
“最佳实践”会是什么样子?
现在,我们正在使用大量的ng-repeat:
<ul>
<li ng-repeat="country in countryList">
{{ country.name }}
<ul ng-if="(stateList | filter:{countryId === country.id}).length">
<li ng-repeat="state in filterStatesByCountryId(country.id)">
{{ state.name }}
<ul ng-if="(cityList | filter:{stateId === state.id}).length">
<li ng-repeat="city in cityList | filter:{stateId === state.id}">{{ city.name }}</li>
</ul>
</li>
</ul>
</li>
</li>
filterStatesByCountryId(country.id)
与stateList | filter:{countryId === country.id}
相同。
我们的应用必须具有绑定,以便在street.name
中更新StreetService
属性时,视图会反映此更改。因此,$scope.streetList = StreetService.all
不是一个开箱即用的选项,而是$scope.streetList
而不是$scope.street = StreetService
,然后将其用作$scope.street.all | filter:{cityId: city.id}
。
必须说这看起来很可怕。
渲染和显示此类数据列表的最佳性能和服务架构最佳方式是什么?
其中一个想法是将整个实体的合并层次结构存储为一个。因此,所有州,城市和街道的国家成为一个对象。然后,country
实体将拥有states {Array.<StateEntity>}
属性,state {StateEntity}
将拥有cities {Array.<CityEnity>}
道具等等。但是如果单个street.name
会更新,我们需要遍历整个country
数据对象以查找我们需要更新的街道,执行更新然后重新渲染视图,或者只有$scope.watch(expr, fn, true)
这对于复杂的层次结构来说是过度的。
感谢。
P.S。我们无法切换到NoSQL来存储数据。
答案 0 :(得分:1)
Angular并不是真正构建来处理关系数据结构我可以看到你在这里尝试做的是模仿C#MVC模板化循环。
事情就是说你有: - 列表中的100个国家=&gt; 100名观察者 - 每个国家20个州的状态=&gt; 2000-ish观察者 - 每个国家/地区30个城市=&gt; 6万观察员
如果您要在一个屏幕上显示所有内容,那么现在这不是您正在做的事情,但要牢记这一点。
作为初步的性能改进,我会在每个ng-repeat语句中添加一个跟踪。
<li ng-repeat="state in filterStatesByCountryId(country.id) track by country.id">
从角度文件中可以看出:
如果您正在处理具有标识符属性的对象,则可以按标识符而不是整个对象进行跟踪。如果您以后重新加载数据,ngRepeat将不必为已经呈现的项重建DOM元素,即使集合中的JavaScript对象已替换为新对象
以及
注意:track by必须始终是最后一个表达式
现在,ng-repeat的性能有点迟钝,我不会双向数据绑定视图属性:
{{ city.name }} => {{ ::city.name }}
这通常可以显着提高你的速度,因为角度不会将观察者绑定到那些领域。
然而,要解决您的基本问题,我会将其建模为单个JSON数据集。但是,您不希望经历变异数据集以使用Angular的麻烦。至少我不会,所以在这种情况下我只想进行简单的单向数据绑定。我不知道街道名称会在多大程度上随时改变。
它看起来像这样:
<li ng-repeat="country in ::countryList track by country.id">
也可以尝试使用controllerAs语法,有助于更清晰的代码。
但是,如果您真的遇到ng-repeat的速度问题,最好根据您的用例编写自己的版本。