【问题标题】:How can I utilize the capabilities of an AngularJS directive to defer rendering content until a click event?如何利用 AngularJS 指令的功能将呈现内容推迟到点击事件?
【发布时间】:2015-10-08 20:50:28
【问题描述】:

在我们的租赁应用程序中,我们进行了一个填充数组的 API 调用,从而触发了 ngRepeat。这将创建一个 div 列表,显示有关出租物业的基本信息。

单击一个属性会展开 div,然后 另一个 API 调用会使用租户列表填充内部 ngRepeat。其中一些物业列出了多达 100 名租户(包括过去和现在)。租户 div 本身也是可扩展的,这揭示了大部分功能。您可以下载租赁协议、查看历史记录等。所有这些功能都是由多个 ng-include 组成的单个指令。

如果您仍在关注,则有一个外部 ngRepeat 和一个内部 ngRepeat,其中包含一个巨大的指令。

<div ng-repeat="properties in property_collection track by property.ID>
    *code removed*
    <div ng-repeat="tenant in property_tenant_collection track by tenant.ID>
    *...code here...*
    <div tenant-menu></div>

当您展开属性列表时,会呈现指令 tenant-menu 和所有附带的 ngInclude 和观察者。他们只是还不可见。单击列表中的租户只会更改 div 的高度,从而显示内部菜单。

这个 UI 的设计方式对性能的影响绝对是可怕的。页面上有超过 15,000 名观察者可以查看您甚至看不到的元素。对一个租户采取行动会无缘无故地触发所有租户的摘要循环。检索必要的数据需要不到一秒的时间,但呈现 60 名申请人的列表几乎需要 20 秒。我已经完全删除了该指令(这意味着当您单击租户时不会发生任何事情)并且加载和渲染时间从 20 秒变为 2-3 秒。

我不确定如何实现这一点,但是否可以推迟附加此指令直到租户被点击?我不想单击租户 div 来更改高度并显示里面的内容,我想立即附加整个指令然后扩展高度。理想情况下,当再次触发 click 事件并且租户崩溃时,我还可以销毁任何观察者并自行清理。

哇。

编辑:臭名昭著的滑动指令粘贴在下面。我认为里面绑定了一个点击事件很奇怪,但也许这是一个好的。 Angular 中的代码模式。我有一种预感,我可以利用 compile、postlink 和 prelink 函数以及接受的答案。我认为我继承了一些遗留代码。

angular.module('jnjManagement.directives').directive('slideableTenant', function($compile, tenantService) {
return {
    restrict: 'A',
    link: function(scope, element, attrs) {
        var targetX, contentX;

        attrs.expanded = false;
        element.bind('click', function() {
            if (!targetX) targetX = document.querySelector(attrs.slideToggleTenant);
            if (!contentX) contentX = targetX.querySelector('.slideable_tenant_content');
            if (!attrs.expanded) {
                contentX.style.border = '1px solid rgba(0,0,0,0)';
                var y = contentX.clientHeight;
                contentX.style.border = 0;
                targetX.style.height = 'auto';
            } else {
                targetX.style.height = '0px';
            }
            attrs.expanded = !attrs.expanded;
        });
    }
};
});

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    理想情况下,您应该有一个属性指令和一个租户指令,并且您确实只会在单击展开元素时加载它的内容。我会使用 Angular 的 $compile。

    $scope.clickHandler = function(){
        $('expanded-element').append($compile('<detail-directive></detail-directive')($scope));
    };
    

    当然,您也希望在元素折叠时清除它们,但听起来您对性能考虑因素有很好的把握。

    【讨论】:

    • 天哪,这完美!单击租户时会有一些延迟,我认为这是因为它正在呈现并且正在获取数据。我正在使用完整指令更新我的问题(缺少上面的代码 sn-p)。如果您对我如何利用 postlink、prelink 和 compile 来获取我的数据、附加菜单、然后展开 div 有任何指示,我将非常感激
    • 很高兴为您提供帮助。我通常只使用链接。如果没有更具体的细节,很难提供帮助。我不知道这些嵌套租户中的每一个的标记有多复杂,并且它可能涉及到足够多的内容(例如,大量的双花括号......)导致显着延迟并且可能需要清理。另外,您检查过 xhr 响应时间吗?也许那里有一个可以按摩的延迟。如果后端无法改进,那么您可以请求/编译/追加小批量记录,以便 UI 在呈现完整记录集时有用。
    • 我想我可以弄清楚。在$compile 完成和下一行代码执行之间似乎有一些延迟。我通过将负责更改 div 高度的代码 sn-p 包装在设置为 500 毫秒的 $timeout 中来测试这个理论。这足以消除口吃并提供更好的体验。在生产中,我将在tenantService 返回它的承诺后执行此代码。你是一个完美的、完美的帮助。
    猜你喜欢
    • 2016-09-02
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    • 2011-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多