【问题标题】:Slow performance with angular material md-select and ng-repeat角度材料 md-select 和 ng-repeat 性能缓慢
【发布时间】:2016-08-14 08:21:59
【问题描述】:

我正在使用 angular 和 angular 材料编写企业应用程序,但对中型(在我看来)形式的性能存在问题。尤其是在 IE 中。

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

表单中最严重的违规者似乎是一些带有 ng-repeat 的 md-selects。

<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-repeats 很小,每个 3-5 个项目。我认为现代浏览器应该处理这种大小的数据集并非常快速地呈现它。所以希望我对我的 HTML 代码做错了什么。数据是从现实生活中的服务器获取的,但我会预先获取它,因此一旦准备好显示表单,它就已经在 $scope 中了。

在使用普通 js 循环获取数据后,我尝试预生成 HTML。然后只插入 html sn-p,如: {{::preGeneratedHtmlHere}}

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

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

【问题讨论】:

  • 如果您可以使用预生成的 html,请尝试绑定 html,例如 ng-bind-html=""。确保你也有 ng-sanitize
  • @Murwa 我尝试将 html 与 ng-bind-html 绑定,但它不起作用。 HTML 包含需要通过 angular 编译才能显示的自定义指令(嗯,角度材料指令)。那么,知道如何将编译后的 HTML 放入 dom 中吗?
  • 这会很棘手,因为你需要 $compile 它
  • 我发现了这个:stackoverflow.com/questions/17417607/… 并且它有效。我会改变所有的重复,然后看看它对性能做了什么
  • 只是让您知道。它确实可以自己进行编译。但它并没有提高性能。我想它仍然是需要插入到 dom 中的相同数量的节点。

标签: angularjs angularjs-ng-repeat angular-material


【解决方案1】:

是的,将它全部变成普通的旧 html 会加快速度,但是那样你就会失去所有的眼球。要获得这两个世界的优点,您可以进行一些基本的优化。

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

    ng-repeat="id in ::serviceReferences"


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

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

PS.:不要煮 $scope 汤!

【讨论】:

  • 这刚好足以让我接受时间。我没有大量的项目,实际上认为动画时间可能太慢了,但这只是将性能提高到可以接受的程度并且工作正常,因为我的列表不会更新。
【解决方案2】:

ng-repeat 中的大量项目会导致一些问题。当 Angular 使用 ng-repeat 创建嵌套列表时,将为每个项目创建一个观察者。数以百计的观察者显然会在 moible(可能还有 IE)上减慢性能。我们曾经在ng-repeat 中遇到过这个问题,所以最好的做法是避免使用ng-repeat,如果可以的话,在你真正需要的时候创建并附加watcher

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

【讨论】:

  • 对,我确实尝试通过使用 {{::id}} 语法来减少观察者的数量。但这似乎与初始加载时间无关。如果做正常循环。我如何附加html。 ng-bind-html 正如@Murwa 所建议的那样?
  • 是的,我看到你使用::id,这是一种单向绑定。如果你想摆脱观察者,你需要自己编写指令,这意味着大量的编码。
【解决方案3】:

Angular 材质的性能很差,因为固定到作用域的对象很大,这使得摘要周期很长且性能不佳。

您应该先尝试使用默认的selectng-options (DOCS HERE)。如果这更适合您,我建议使用纯 html,然后使用 MaterializeCSS 来获得 Material Design 的外观和感觉。

【讨论】:

  • 我明白了,我会尝试将其转换为纯 html 选择,看看性能会发生什么
  • 我现在在没有任何 css 样式的情况下对其进行了测试。而在 chrome 中,表单现在非常快。 IE 也有所改进,但还不够好。
  • 我选择这个作为接受的答案,因为这样做大大提高了性能。然而,为了获得足够好的最终用户体验,我还结合了 ng-if 和 ng-show。这样 ng-if = true 在 moseover 上,然后 ng-show = true 在点击上。这在 explorer 和 chrome 中都创建了非常快速的表单!
  • 我在这里解释了我的技术:stackoverflow.com/a/36795321/1226268 供任何人在 google 上找到它。
  • 其实对象没必要很大,看你定义什么。摘要周期也是关于更新的,而原始问题抱怨初始(编译+链接)性能。正如我在回答stackoverflow.com/questions/36764414/… 中所写,这是因为 md-select 会编译所有选项。这可以推迟到单击下拉菜单为止。可能通过让列表成为焦点来微调它。
猜你喜欢
  • 1970-01-01
  • 2015-06-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-29
  • 2016-04-12
  • 2020-06-17
相关资源
最近更新 更多