简体   繁体   English

AngularJS具有许多指令的性能

[英]AngularJS performance with many directives

I'm using AngularJS 1.0.8. 我正在使用AngularJS 1.0.8。

The problem: I have a dynamic website that can be built from various components, or widgets: paragraphs, text blocks, images, hyperlinks, and tables, for that matter. 问题:我有一个动态网站,可以从各种组件或小部件构建:段落,文本块,图像,超链接和表格。 A paragraph is a container of more components. 段落是更多组件的容器。 A table is also a kind of a container - it can hold other components, and it arranges them as a datagrid. 表也​​是一种容器 - 它可以容纳其他组件,并将它们排列为数据网格。

The website is not static, ie I don't have a pre-defined layout of such components. 该网站不是静态的,即我没有这种组件的预定义布局。 Instead, I get a JSON in startup, that specifies the layout of the components. 相反,我在启动时获得了一个JSON,它指定了组件的布局。

Originally, I had a directive of each such component, using templates for that directives, and occasionally using $compile to change the DOM a bit for more complex components. 最初,我有一个每个这样的组件的指令,使用该指令的模板,偶尔使用$ compile为更复杂的组件更改DOM。 For the 'container' components - paragraphs and tables - I used ngRepeat to render all of the components that are contained in that container-component. 对于'容器'组件 - 段落和表 - 我使用ngRepeat来呈现该容器组件中包含的所有组件。

That was problematic performance-wise. 这在性能方面存在问题。 It would take the website many seconds to load on Chrome/Firefox, with the time spent mainly in the AngularJS render mechanism (not in IO, I figured). 这个网站需要花费很多秒才能在Chrome / Firefox上加载,主要花费在AngularJS渲染机制上的时间(不在IO中,我想)。

So I decided to change the directives of these components. 所以我决定改变这些组件的指令。 Instead of using ngRepeat, which is not really necessary since I don't need the two-way binding (the content in the website is not interactive and cannot be changed, so really I only need to render it once, very much like a servlet) - I built the HTML string in the directive myself, using plain JS, iterating over all of the contained components that exist in the model, and at the end I $compiled and linked it. 而不是使用ngRepeat,这不是真正必要的,因为我不需要双向绑定(网站中的内容不是交互式的,无法更改,所以我只需要渲染一次,非常像servlet ) - 我自己在指令中构建了HTML字符串,使用普通的JS,迭代模型中存在的所有包含的组件,最后我编译并链接它。

The result wasn't good enough again. 结果再也不够好了。 For a table of a few hundered cells, it took ~500 milis to link in modern Chrome/Firefox, and ~4000 milis in IE9, and ~15000 milis in IE8, and IE7 is still rendering so I can't give you the time :) 对于一些数量较少的细胞表,在现代Chrome / Firefox中连接约500 milis,在IE9中连接约4000 mil,在IE8中约需15,000 milis,IE7仍在渲染,所以我无法给你时间:)

I thought that the problem might be with an extensive use of directives. 我认为问题可能在于广泛使用指令。
A simple: 一个简单的:

<div my-table-component data="data"></div>

element would result, after the link, in a <table> tag with 30-40 <tr> tags, each with 10 <td> tags, and in each there would be an additional <div my-text-component> or <div my-image-component> that would then have to be compiled and linked by itself (since it has a directive). 在链接之后,元素将在<table>标记中生成30-40个<tr>标记,每个标记包含10个<td>标记,并且每个标记中都会有一个额外的<div my-text-component><div my-image-component>然后必须自己编译和链接(因为它有一个指令)。

I though that since my website is not interactive to begin with, I don't really need this. 我虽然因为我的网站开头并不是互动的,所以我真的不需要这个。 Maybe I could avoid using directives for each component, and leave only a directive for the container-components. 也许我可以避免为每个组件使用指令,只留下容器组件的指令。 In these directives, I would create the actual HTML template of every possible other component, instead of using directives that would do that. 在这些指令中,我将创建每个可能的其他组件的实际HTML模板,而不是使用那样做的指令。

That takes me another step away from the AngularJS idea towards a servlet idea. 这让我从AngularJS的想法向另一个步骤转向了servlet的想法。 And it kind of sucks. 它有点糟糕。 So maybe one of you can offer a better approach for me... Maybe the performance problem is not even there? 所以也许你们其中一个人可以为我提供更好的方法......也许性能问题甚至不存在? Maybe a use of directives (and hopefully ngRepeat) can be fine performance-wise even with this amount of items? 即使有这么多的项目,也许使用指令(并希望ngRepeat)可以很好地表现性能? Maybe there's a better way to make an insightful performance benchmark, other than using Chrome's Developer Tools, Firebug, and Chrome's Batarang AngularJS extension (none of them really directed me in a productive way). 除了使用Chrome的开发者工具,Firebug和Chrome的Batarang AngularJS扩展(没有一个真正指导我以高效的方式)之外,也许有更好的方法来制作富有洞察力的性能基准测试。

Using a lot of nested directives by itself is not a problem, but any extensive binding could have huge impacts. 使用大量嵌套指令本身不是问题,但任何广泛的绑定都可能产生巨大影响。

If someone is still looking for an aswer to this, using Angular 1.3+, OP could solve his problem by first using one-time binding on all the elements on which he says there is "no need for two-ways bindings", using the ::binding syntax. 如果有人仍然在寻找一个aswer,使用Angular 1.3+,OP可以通过首先对他说“不需要双向绑定”的所有元素使用一次性绑定来解决他的问题,使用::binding语法。

In addition, I would suggest trying to spot which bindings exactly are being particularly slow, using the amazing profiling snippets from this website: http://bahmutov.calepin.co/improving-angular-web-app-performance-example.html 此外,我建议尝试使用本网站上惊人的分析片段来确定哪些绑定确实特别慢: http//bahmutov.calepin.co/improving-angular-web-app-performance-example.html

Finally, what often takes most time in Angular, especially while building big ng-repeated tables, is the compilation phase. 最后,在Angular中经常花费大部分时间,特别是在构建大型重复表时,是编译阶段。 So if possible try to only build a restricted number of elements (using limitTo ) and then load more as the user scrolls for instance. 因此,如果可能的话,尝试仅构建有限数量的元素(使用limitTo ),然后在用户滚动时加载更多元素。 Many directives address this concern (look for "infinite scrolling") 许多指令解决了这个问题(寻找“无限滚动”)

All in all, I think it is still worth trying to optimize an Angular application rather tham switching to native JS, most of the time the lag comes from a developper mistake: some applications have thousands of watchers and run pretty smoothly (*cough* like mine *cough*). 总而言之,我认为仍然值得尝试优化Angular应用程序而不是切换到本机JS,大多数时候滞后来自开发人员的错误:一些应用程序有成千上万的观察者并且运行得非常顺利(*咳嗽*喜欢我的咳嗽*)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM