angular material md-select 和 ng-repeat 性能缓慢

Slow performance with angular material md-select and ng-repeat

我正在使用 angular 和 angular material 编写企业应用程序,但我对中型(我认为)表单的性能有疑问。尤其是在 IE 中。

(工作演示,请参阅 https://codepen.io/tkarls/pen/vGrqWv。点击卡片标题,它会在打开前稍微暂停。尤其是使用 IE 和移动设备。桌面 chrome 效果很好。)

表格中最严重的违规者似乎是 md-selects 身上有 ng-repeat。

<md-select ng-model="form.subchannelId" ng-disabled="vm.readOnly">
    <md-option ng-repeat="id in subchannelIds" value="{{::id}}">{{::id}}</md-option>
</md-select>
<md-select ng-model="form.serviceReference" ng-disabled="vm.readOnly">
    <md-option ng-repeat="id in serviceReferences" value="{{::id}}">{{::countryId}}{{::id}}</md-option>
</md-select>
<md-select ng-model="form.audioCodec" ng-disabled="vm.readOnly">
    <md-option ng-repeat="audioCodec in audioCodecs | orderBy:'toString()'" value="{{audioCodec}}">{{::systemVariables.encoders.aac[audioCodec].displayName}}</md-option>
</md-select>
<md-select ng-model="form.audioSource" ng-disabled="vm.readOnly">
    <md-option ng-repeat="audioSource in audioSources | orderBy:'toString()'" value="{{audioSource}}">{{audioSource}}</md-option>
</md-select>
<md-select ng-model="form.padSource" ng-disabled="vm.readOnly">
    <md-option ng-repeat="padSource in padSources | orderBy:'toString()'" value="{{::padSource}}">{{::padSource}}</md-option>
</md-select>
<md-select ng-model="form.lang" ng-disabled="!form.generateStaticPty || vm.readOnly">
    <md-option ng-repeat="langKey in langKeys | orderBy:'toString()'" value="{{::langs[langKey]}}">{{::langKey}}</md-option>
</md-select>
<md-select ng-model="form.pty" ng-disabled="!form.generateStaticPty || vm.readOnly">
    <md-option ng-repeat="ptyKey in ptyKeys | orderBy:'toString()'" value="{{::ptys[ptyKey]}}">{{::ptyKey}}</md-option>
</md-select>

数据模型如下所示:

$scope.subchannelIds = [0, 1, 2]; //up to 63 in real life
$scope.serviceReferences = ["000", "001", "002"]; //up to 999 in real life
$scope.ptys = {
  "No programme type": 0,
  "News": 1,
  "Current Affairs": 2}; //Up to ~30 in real life
$scope.ptyKeys = Object.keys($scope.ptys);
$scope.langs = {
  "Unknown": "00",
  "Albanian": "01",
  "Breton": "02"}; //Up to ~100 in real life
$scope.langKeys = Object.keys($scope.langs);

其他 ng-repeat 个小,每个有 3-5 个项目。我认为现代浏览器应该处理这种大小的数据集并非常快速地呈现它。所以希望我的 HTML 代码做错了什么。数据是从现实生活中的服务器获取的,但我这样做 pre-fetch 所以一旦表单准备好显示它就已经在 $scope 中了。

在使用普通的 js 循环获取数据后,我尝试 pre-generate HTML。然后只插入 html 片段,例如: {{::preGeneratedHtmlHere}}

但是 angular 不会将其视为 html 而是文本...

感谢任何关于如何优化它的帮助!

ng-repeat 中的大量项目会导致一些问题。当 angular 使用 ng-repeat 创建嵌套列表时,将为每个项目创建一个观察者。数以百计的观察者会明显降低移动设备(和 IE 可能)的性能。我们曾经在 ng-repeat 中遇到过这个问题,所以最好的做法是尽可能避免使用 ng-repeat,在真正需要时创建并附加 watcher

所以我认为可能的解决方案是,尝试使用普通的 for 循环而不是 ng-repeat

Angular material 性能很差,因为固定到范围的对象很大,这使得摘要周期很长且性能不佳。

您应该先尝试使用默认的 selectng-optionsDOCS HERE). If this works better for you, I'd suggest using plain html and then use MaterializeCSS 以获得 Material 设计的外观。

是的,把它全部改成旧的 html 会加快它的速度,但是那样你就失去了所有的视觉享受。为了获得两个世界的优点,你可以做一些基本的优化。

  1. 你真的需要看合集吗-是合集吗 要改变,如果是这样,你不能触发摘要吗?正如你所做的 使用 id,您还可以将重复的集合单向绑定为 嗯

    ng-repeat="id in ::serviceReferences"


  1. 你真的不需要 预装了所有选项,对吗?既然你正在使用 angular-material,默认下拉会换成 多个元素,以模拟下拉行为。我只是 删除选项列表,将其替换为实际选择的 元素并仅在控件获得时填充列表 重点。参见 documentation

我仍然同意 angular-material 的性能不佳。它根本不能很好地扩展。 1-2 个控件可以工作,但如果你有超过 10 个控件,它就会开始失败。

PS.: 不要煮 $scope 汤!