在 Angular JS应用程序中响应JS注入或者战斗提高性能

分享于 

11分钟阅读

Web开发

  繁體

介绍

它不会发现有数百个插件和库,这简化了现代web界面的构建。 其中一个是 AngularJS。

有许多关于它的性能的文章;它的中大多数关注的是不要做好事情。 它认为只有不正确的应用程序是慢的,正确的应用程序不应该包含超过 2000个DOM元素。 如果它们包含更多的东西,那么就。 虽然这个语句非常有效,但有时你必须编写一个"错误"网络应用程序,因为你有。 在本文中,我们将介绍此类任务的一个,以及如何解决它。 我们相信这篇文章对于专业的网站开发者来说是有用的。

所以,我们的任务是为体育俱乐部预订系统开发日历。 日历表示七个 12-hour 块,让我们来称之为天。 每天分为 15-minutes 间隔( 查看下面的截图) ;每个间隔( 单元格) 可以包含从 2到 10的DOM元素。 到目前为止,元素的峰值数大约为 3000.

让我们开始工作吧

<divng-repeat="day in days"> 
. . ..
 <divng-repeat="hour in day.hours"><divng-repeat="block in hour.blocks">. . .
 <divng-repeat="block in hour.blocks">. . .
 <divng-repeat="session in block.sessions">. . .
 </div></div></div></div></div>

完成但是,所有这些元素的数据绑定占用了 2 -3秒。 对了,这里有一个问题: 如何测量一般数据绑定的数量? 试图使用探查器进行它并不回答问题,因为很难区分数据绑定,由路由等所添加的内容。

因此,我们简化了以下步骤:

$timeout(function() {
 $scope.days = days;
 var now = new Date();
 $timeout(function() { 
 console.log(new Date - now);
 $scope.apply()
 }, 0);
}, 100);

第一个超时是所有它的他脚本完成,而不是违反测量精度的第一个时间,数字 100 ( ms )。 第二个超时可以设置为 0,因为浏览器可能会立即执行 $timeout的内部处理程序。

2-3秒是来自UI响应性观点的相当大的数字,因此如何减少时间?

首先,值得一读的是: tech.small-improvements.com/2013/09/10/angularjs-performance-with-large-lists/,当然,这是: 优化 AngularJS: 1200ms 至 35毫秒。 后一篇文章,顺便说一句,显示出了。 但是,结果是通过虚拟化( 例如 ) 实现的。 只有可见部分渲染和缓存。 虚拟化是一个很好的解决方案,但是只有当内容不太复杂时。 否则,在滚动页面时会出现不愉快的延迟,这会削弱所有的。

谈到虚拟化:有一个伟大的AngularJS MODULE 称为 ngGrid,可以显示数百万( 看看) 元素。 ! 但是这个秘密 behind 又是( 否则,ngGrid 中的所有行都具有相同的高度)的虚拟化。

最后,通过尝试和错误我们来 ReactJS。 库的开发人员声称它是数据绑定的最快框架,现在我们倾向于使用它。 尽管在sheet1网站上表达了相反的观点,我们自己的测试显示了React的优势。

现在React。

有许多关于React框架的文章,就像这样:

ReactJS的秘密在于它操作虚拟 DOM ;因此它可以最小化渲染视图所需的操作数量。

在React中呈现视图的代码如下所示:

var Hello = React.createClass({
 render: function() {
 return React.DOM.div({}, 'Hello ' + this.props.name);
 }
}); 
React.renderComponent(Hello({name: 'World'}), document.body);

这里的第一部分定义了组件,然后由该行呈现:

"React.renderComponent(Hello({name: 'World'}), document.body)"

API React.DOM 比较方便。 然而,与 Angular 和bash模板相比,通过JavaScript生成DOM看起来有些过时,而且看起来相当耗时。 Facebook为解决这个问题提供了"在浏览器JSX转换中"。

变压器满足时

<script type="text/jsx">

在浏览器中,它将这里代码转换为

var HelloMessage = React.createClass({
 render: function() {
 return <div>{'Hello ' + this.props.name}</div>;
 }
});

到这里:

var Hello = React.createClass({
 render: function() {
 return React.DOM.div({}, 'Hello ' + this.props.name);
 }
}); 

注意返回 [Html markup]的语法;它不带引号( 然而,从 ReactJS.Net, 附加括号或者线条的经验不会伤害到)。 要显示 array的元素,需要执行以下操作:

var HelloMessage = React.createClass({
 render: function() {
. . . 
 var nodes = array.map(function(element) {
 return <div>...</div>;
 });
 return <div>{nodes}</div>;
 }
});

但是,很可能,你会这样做:

var SubMessage = React.createClass({
 render: function() {
 return <div>...</div>;
 }
});var HelloMessage = React.createClass({
 render: function() {
. . . 
 var nodes = array.map(function(element) {
 return <SubMessage>. ..</SubMessage>;
 });
 return <div>{nodes}</div>;
 }
});

为什么答案在于组件需要在下面描述自己的状态。

顺便说一下,可以将JSX转换委派给服务器;存在广泛的集成: 这就是我们所做的,在我们的案例中,它是 ReactJS.Net.

好的,这两种方法的结合,MV-*框架的基石? 由于在 /building-robust-web-apps-with-react-part-1.html 中显示,ReactJS不像这样出现,但存在一些解决问题的方法。 组件的属性和状态在ReactJS中不同。 属性是通过调用以下方法传递给组件 React.renderComponent(Hello({[PROPERTIES]}),.. .) 在大多数情况下使用 this.props. 接收 inside 组件,属性是用于生成HTML标记的对象树。

Ideologically,属性假定一个相当 static的行为。 若要在更改属性时刷新标记,必须调用 React.renderComponent。 然而,从经验来看,renderComponent 通常比MV-*框架的结构要快得多,因为搜索差异很好。

一个 State 可以改变。 有 2种主要方法可以用于处理 State:

  • getInitialState - 返回组件( 将根据属性返回)的初始 State
  • setState - 设置 State

当调用特定组件的setState 时,只会呈现该组件。

如何将数据推回? 这要求 valueLink 对象提供初始值和更改处理程序。 这里处理程序必须根据情况进行操作。 Facebook不推荐将新值推入道具,因这里我们必须将 State 设置为新值,以便根据数据刷新标记。 换句话说,ReactJS中的双向绑定将类似于以下内容:

Angular 中的内容为:

<inputng-model=value />. 

在ReactJS中将是:

var HelloMessage = React.createClass({
 getInitialState() {
 return { value: this.props.value };
 }, 
 render: function() {
 var valueLink = {
 value: this.state.value,
 requestChange: function(newValue) {
 this.setState({value: newValue});
 }.bind() // Pay attention to the call of. bind() };
 return <input value={valueLink}/>;
 }
});

太长了这是对的这是我们的五次性能提升的价格。 !

回到我们的任务下面是我们的任务:

  • 包含缓慢工作部件的AngularJS应用程序
  • 我们希望提高性能( 实际上,五倍的增加效果很好) ;
  • 我们希望以最少的努力实现 上面 ;
  • 我们希望只修改应用程序的视图部分,并保持控制器和模型不变。

这个想法在 http://www.williambrownstreet.net/blog/2014/04/faster-angularjs-rendering-angularjs-and-reactjs/http://davidchang.github.io/ngReact/描述。

因此,我们的:

<divng-repeat="day in days"> 
. . ..</div>

转换为:

<divcalendar="days"/>

这不是React- 它仍然是 Angular,日历是一个跟踪日期更改的指令,并调用 renderComponent

好消息是,视图代码几乎可以通过机械方式变成 JSX。 ng类转换为 className= {className},其中类名只表示类的( 请确保它完全是类别和非类;如果你意外地混合它们,React将给你提示。)的计算名称。 ng显示转换为 style= {style}。 ng-model 变成了 上面 ( 查看上面列出的HelloMessage组件)。 这个过程非常简单,甚至有ngReact库可以自动完成它。 但是,就像这里所示,性能可能存在问题。 为了避免这种情况,我们选择了经过验证的"手册"方法。

结果是

什么是 2 -3,现在采取了 300. 这使得用户体验非常愉快。 返工过程花费了我们大约 3天的时间,而初始实现大约为 15天。 我们已经尽可以能地改变了视图的变化,但也许它是这个特定任务的一个特定。

最后,值得说明的是,使用React"注入"( 如果允许我们在 Angular 应用程序中调用它)。 最重要的是,尽管修改大部分是手工和机械的,但它们在本地应用。 我们相信,在类似的情况下,React可以是一种"魔杖"加速应用程序的"慢速"部分。


angular  react  PERF  性能  入侵  FIG