Javascript AngularJS性能问题
我正在构建一个复杂的angular应用程序,它可以无限滚动marsonry类的列和图像。我做了一项研究,并编写了自己的指令,为我呈现数据:Javascript AngularJS性能问题,javascript,html,performance,angularjs,lag,Javascript,Html,Performance,Angularjs,Lag,我正在构建一个复杂的angular应用程序,它可以无限滚动marsonry类的列和图像。我做了一项研究,并编写了自己的指令,为我呈现数据: angular.module('deepsy.flexgrid', []); angular.module('deepsy.flexgrid').directive('flexgrid', [ 'flexgridFactory', function initialize(flexgridFactory) { return
angular.module('deepsy.flexgrid', []);
angular.module('deepsy.flexgrid').directive('flexgrid', [
'flexgridFactory',
function initialize(flexgridFactory) {
return flexgridFactory.create();
}
]);
angular.module('deepsy.flexgrid').factory('flexgridFactory', [
'FlexGrid',
'$log',
function initialize(FlexGrid, $log) {
function Creator() {
this.restrict = 'AE';
this.scope = {
'model': '=source',
'opts': '=options'
};
this.$$grid = null;
this.link = this.$$link.bind(this);
}
Creator.prototype.$$link = function $$link(scope, elem, attrs) {
scope.itemTemplate = attrs.template;
scope.mother = scope.$parent;
scope.template = elem.html();
elem.html('');
this.$$grid = new FlexGrid(scope, elem);
};
return {
create: function create() {
return new Creator();
}
};
}
]);
angular.module('deepsy.flexgrid').factory('FlexGrid', [
'$compile',
function($compile) {
function FlexGrid(scope, elem) {
this.scope = scope;
this.elem = elem;
this.state = null;
this.counter = 0;
this.id = Math.floor(Math.random() * 999);
this.$getColumns();
this.$createColumns();
window.onresize = this.$watchSize.bind(this);
this.scope.$watch(function() {
return this.scope.model;
}.bind(this), this.$applyData.bind(this), true);
}
FlexGrid.prototype.$getColumns = function() {
var curr = null,
width = document.body.clientWidth,
min, max;
for (var i in this.scope.opts.columns) {
curr = this.scope.opts.columns[i];
min = curr.min || 0;
max = curr.max || 99999;
if (min < width && width < max) {
this.state = curr;
return curr;
}
}
};
FlexGrid.prototype.$createColumns = function() {
var output = [];
for (var i = 0; i < this.state.columns; i++) {
output.push('<div id="flexgrid_' + this.id + '_' + i + '" class="gridColumns ' + this.state.class + '"></div>');
}
this.elem.html(output.join(''));
};
FlexGrid.prototype.$watchSize = function() {
var curr = this.state || {
columns: 0
};
this.$getColumns();
if (this.state.columns != curr.columns) {
this.$createColumns();
this.$fillData(0);
}
};
FlexGrid.prototype.$applyData = function(newVal, oldVal) {
var bindings = [],
count = 0;
oldVal.forEach(function(obj) {
bindings.push(obj._id);
});
newVal.forEach(function(obj) {
if (bindings.indexOf(obj._id) != -1) {
count++;
}
});
if (count == oldVal.length && oldVal.length > 0) {
this.$fillData(count);
// console.log('add');
} else {
this.$fillData(0);
// console.log('render');
}
};
FlexGrid.prototype.$fillData = function(start) {
var columns = this.state.columns,
len = this.scope.model.length;
if (start === 0) {
this.$clearColumns(columns);
this.counter = 0;
}
for (var i = start; i < len; i++) {
$("#flexgrid_" + this.id + "_" + this.counter).append(this.$compile(this.scope.model[i]));
if (this.counter++ === columns - 1)
this.counter = 0;
}
//$("img", this.elem).load(function(){
// $(this).parent().fadeIn(700);
//});
};
FlexGrid.prototype.$compile = function(data) {
var compiled = this.scope.template.replace(/\{\|[^\|\}]*\|\}/gmi, function(exp, val) {
return data[exp.replace(/\|\}|\{\|/gmi, '')];
});
compiled = compiled.replace('src-image', 'src="' + data.image + '" dinimg');
return compiled;
};
FlexGrid.prototype.$clearColumns = function(columns) {
for (var j = 0; j < columns; j++) {
$("#flexgrid_" + this.id + "_" + j).empty();
}
};
return FlexGrid;
}
]);
我发现我只有一个观察者!因此,观察者可能不是问题所在。通过这段代码,我实现了无限滚动。每个元素包含图像和文本。问题是,在获得超过200-250项后,我的UI开始滞后,即使我有一个观察者。我认为这可能是因为图像大小,但在Chrome控制台执行$(“.item”).html(“”)并清除所有框的内容后,我的UI仍然不平滑。这个问题不是由太多的DOM元素引起的,因为除了指令呈现的div之外,我总共只得到了38个div。如何提高我的应用程序的性能
编辑:我还注意到一件奇怪的事情,即使我通过$(“.item”)从DOM中删除所有元素(渲染后)。删除,浏览器仍然使用300mb+RAM。我会使用插件再次检查观察者计数,该插件有一个性能选项卡,您可以在其中查看所有手表
下面是如何使用chrome开发工具评测内存的摘要
堆分配配置文件:记录随时间的分配
- 打开chrome开发工具
- 打开配置文件选项卡
- 单击堆分配配置文件
- 单击开始
- 执行将数据加载到网格中所需的操作
- 单击“停止”
堆快照:记录实际分配的对象
- 打开chrome开发工具
- 打开配置文件选项卡
- 单击堆快照
- 单击“拍摄快照”
- 执行将数据加载到网格中所需的操作
- 再次单击左上角的“配置文件”
- 单击“拍摄快照”
- 运行
$(“.item”).html(“”)
- 再次单击左上角的“配置文件”
- 单击“拍摄快照”
- 单击左侧3个配置文件中的一个,然后查看实例
您还可以:
- 单击左侧3个配置文件中的一个
- 现在,在顶部栏中,将下拉列表设置为“Comparison”
- 在“Comparison”选项旁边,选择要比较的快照
好的,很好。您是否尝试在$(“.item”).html(“”)
前后拍摄堆分配配置文件(使用Chrome开发工具)和堆快照以查看剩余的对象类型?您能否简单解释一下我如何做到这一点?它是否有助于找到原因?@Deepsy,prb是什么?我们对图像进行了更多优化,以及删除无休止滚动中的第一个项目,因此现在更加平滑。
(function () {
var root = $(document.getElementsByTagName('body'));
var watchers = [];
var f = function (element) {
if (element.data().hasOwnProperty('$scope')) {
angular.forEach(element.data().$scope.$$watchers, function (watcher) {
watchers.push(watcher);
});
}
angular.forEach(element.children(), function (childElement) {
f($(childElement));
});
};
f(root);
console.log(watchers.length);
})();