渲染许多条目并不是很慢。问题是每当 onAuthUIStateChange((authState, authData) => {
console.log('LoginPage', authState, authData);
if (this.authState == AuthState.SignedIn) {
this.router.navigate(['']);
}
});
更新时,它首先在元素的末尾添加新项目,然后在它匹配新的 $scope.data
时减少它。
例如:
$scope.data
此脚本正在更新 <div class="list" ng-repeat="entry in data">
<h3>{{entry.title}}</h3>
</div>
:
$scope.data
假设我在 $scope.load = function() {
$scope.data = getDataFromDB();
}
中有 5 个条目。条目是:
$scope.data
当 [
{
id: 1,
title: 1
},
{
id: 2,
title: 2
},
......
]
已经有这些条目然后被重新加载($scope.data
被调用)时,DOM 元素大约 0.1s - 0.2s 有 10 个元素(重复元素),然后在 0.1s 之后 - 0.2s 减少到 5.
所以问题是在更新 ng-repeat DOM 时有大约 0.1s - 0.2s 的延迟。当我实施实时搜索时,这看起来非常糟糕。每当它从数据库中更新时,ng-repeat DOM 元素都会在短时间内添加一次。
如何使渲染即时?
我会把我所有的代码粘贴在这里:
控制器:
$scope.data = getDataFromDB();
视图:
$scope.search = function (table) {
$scope.currentPage = 1;
$scope.endOfPage = false;
$scope.viewModels = [];
$scope.loadViewModels($scope.orderBy, table);
}
$scope.loadViewModels = function (orderBy, table, cb) {
if (!$scope.endOfPage) {
let searchKey = $scope.page.searchString;
let skip = ($scope.currentPage - 1) * $scope.itemsPerPage;
let searchClause = '';
if (searchKey && searchKey.length > 0) {
let searchArr = [];
$($scope.vmKeys).each((i, key) => {
searchArr.push(key + ` LIKE '%` + searchKey + `%'`);
});
searchClause = `WHERE ` + searchArr.join(' OR ');
}
let sc = `SELECT * FROM ` + table + ` ` + searchClause + ` ` + orderBy +
` LIMIT ` + skip + `, ` + $scope.itemsPerPage;
sqlite.query(sc, rows => {
$scope.$apply(function () {
var data = [];
let loadedCount = 0;
if (rows != null) {
$scope.currentPage += 1;
loadedCount = rows.length;
if (rows.length < $scope.itemsPerPage)
$scope.endOfPage = true
for (var i = 0; i < rows.length; i++) {
let item = rows.item(i);
let returnObject = {};
$($scope.vmKeys).each((i, key) => {
returnObject[key] = item[key];
});
data.push(returnObject);
}
$scope.viewModels = $scope.viewModels.concat(data);
}
else
$scope.endOfPage = true;
if (cb)
cb(loadedCount);
})
});
}
}
调用它:
<div id="pageContent" class="root-page" ng-controller="noteController" ng-cloak>
<div class="row note-list" ng-if="showList">
<h3>Notes</h3>
<input ng-model="page.searchString" id="search"
ng-keyup="search('notes')" type="text" class="form-control"
placeholder="Search Notes" style="margin-bottom:10px">
<div class="col-12 note-list-item"
ng-repeat="data in viewModels track by data.id"
ng-click="edit(data.id)"
ontouchstart="touchStart()" ontouchend="touchEnd()"
ontouchmove="touchMove()">
<p ng-class="deleteMode ? 'note-list-title w-80' : 'note-list-title'"
ng-bind-html="data.title"></p>
<p ng-class="deleteMode ? 'note-list-date w-80' : 'note-list-date'">{{data.dateCreated | displayDate}}</p>
<div ng-if="deleteMode" class="note-list-delete ease-in" ng-click="delete($event, data.id)">
<span class="btn fa fa-trash"></span>
</div>
</div>
<div ng-if="!deleteMode" ng-click="new()" class="add-btn btn btn-primary ease-in">
<span class="fa fa-plus"></span>
</div>
</div>
<div ng-if="!showList" class="ease-in">
<div>
<div ng-click="back()" class="btn btn-primary"><span class="fa fa-arrow-left"></span></div>
<div ng-disabled="!isDataChanged" ng-click="save()" class="btn btn-primary" style="float:right">
<span class="fa fa-check"></span>
</div>
</div>
<div contenteditable="true" class="note-title"
ng-bind-html="selected.title" id="title">
</div>
<div contenteditable="true" class="note-container" ng-bind-html="selected.note" id="note"></div>
</div>
</div>
<script src="../js/pages/note.js"></script>
sqlite 查询:
$scope.loadViewModels($scope.orderBy, 'notes');
它是 apache cordova 框架,所以它在 Android 模拟器中使用 webview。
query: function (query, cb) {
db.transaction(function (tx) {
tx.executeSql(query, [], function (tx, res) {
return cb(res.rows, null);
});
}, function (error) {
return cb(null, error.message);
}, function () {
//console.log('query ok');
});
},
所以控制器里面有控制器。父项为 <html ng-app="app" ng-controller="pageController">
<head>....</head>
<body>
....
<div id="pageContent" class="root-page" ng-controller="noteController" ng-cloak>
....
</div>
</body>
</html>
,子项为 pageController
。这样的结构是否会减慢 noteController
指令的速度?
顺便说一句,使用 ng-repeat
没有帮助。渲染时仍然有延迟。我也可以修改条目,所以当条目更新时,它也应该在列表中更新。
经过彻底调查后,发现了一些奇怪的东西。通常 ng-repeat 项目中有 track by
键。在我的情况下 ng-repeat 项目没有它。这是问题的原因吗?
答案 0 :(得分:2)
提高性能的一种方法是在 track by
表达式中使用 ng-repeat
子句:
<div class="list" ng-repeat="entry in data track by entry.id">
<h3>{{entry.title}}</h3>
</div>
来自文档:
<块引用>最佳实践:如果您正在处理具有唯一标识符属性的对象,则应通过此标识符而不是对象实例进行跟踪,例如item in items track by item.id
。如果您稍后重新加载数据,ngRepeat
将不必为它已经呈现的项目重建 DOM 元素,即使集合中的 JavaScript 对象已替换为新的对象。对于大型集合,这显着提高了渲染性能。
有关详细信息,请参阅
答案 1 :(得分:0)
在你的 html 中,试试这个:
<div class="list" ng-repeat="entry in data">
<h3 ng-bind="entry.title"></h3>
</div>
答案 2 :(得分:0)
经过深入研究,我发现了我的问题。每次我重置/重新加载我的 $scope.viewModels
时,我总是先将它分配给 null / empty array
。这就是导致渲染延迟的原因。
示例:
$scope.search = function (table) {
$scope.currentPage = 1;
$scope.endOfPage = false;
$scope.viewModels = []; <------ THIS
$scope.loadViewModels($scope.orderBy, table);
}
因此,我没有将其分配给空/空数组,而是将其替换为新加载的数据,并且闪烁消失了。