【问题标题】:Angular ng-if and ng-show combinationAngular ng-if 和 ng-show 组合
【发布时间】:2015-01-24 18:20:49
【问题描述】:

想象一下可能会在网页上呈现的一些繁重的内容,例如图表。 Angular 提供了 2 个选项来切换所述内容的可见性。

ng-show 将呈现内容而不管表达式如何,并在事后简单地“隐藏”它。这并不理想,因为用户可能永远不会在会话期间“打开”内容,因此渲染它是一种浪费。

ng-if 在这方面更好。如果表达式为假,使用它代替 ng-show 将首先防止重内容被渲染。但是,它的优点也是它的弱点,因为如果用户隐藏图表然后再次显示,则每次都会从头开始渲染内容。

我怎样才能制定一个两全其美的指令?这意味着它像 ng-if 一样工作,直到第一次渲染内容,然后切换到像 ng-show 一样工作,以防止每次重新渲染它。

【问题讨论】:

标签: angularjs angularjs-directive


【解决方案1】:

+1 对 Denis 的回答,但为了完整起见,它甚至可以通过将逻辑保留在视图中而不“污染”控制器来进一步简化:

<button ng-click="show = !show">toggle</button>
<div ng-if="once = once || show" ng-show="show">Heavy content</div>

plunker

编辑:上述版本可以通过一次性绑定进一步改进(和简化),以减少once 上不必要的 $watch - 这仅适用于 Angular 1.3+:

<div ng-if="::show || undefined" ng-show="show">Heavy content</div>

需要undefined 以确保观察值在变为true 之前不会"stabilize"。一旦它稳定下来,它也会失去 $watch,因此它不会受到对show 的任何进一步更改的影响。

【讨论】:

  • 很棒的提示,我会想办法以某种方式重用它!
  • 绝招!但是有没有办法在必要时重新渲染指令?
【解决方案2】:

您可以通过同时使用ngIfngShow 来使其工作,其中每个都是不同变量的控制器。 ngIf 将被设置为true 一次,并且永远不会再次设置为false,而ngShow 将根据用户的需要进行切换。

看看这个fiddle

【讨论】:

    【解决方案3】:

    @new-dev 的回答激发了我自己的组合想法,即使用切换按钮快速获得相当重的组件。

    我最初的问题是我的页面由大约 20 个组件组成,每个组件需要大约 1 秒的时间来加载。每个都由一个按钮切换。

    如果使用普通的 ng-if,我会在按下切换按钮后获得即时页面加载和 1 秒延迟。

    如果使用普通的 ng-show,我会得到即时切换按钮,但页面加载延迟 20 秒...

    所以,现在我也将它们与 ng-mouseenter 控件结合起来。像这样。

    <div ng-mouseenter="create=true">
        <button ng-click="showAll = !showAll"></button>
        <!--lightweight content-->
        <div ng-show="showAll">
            <div ng-if="create">
                <!--Heavy content-->
            </div>
        </div>
    </div>
    

    这给了我在 chrome 和 IE 中的出色表现。用户进入组件后实际点击按钮所花费的时间用于 DOM 创建。然后,一旦(如果)点击到达,DOM 节点就会快速显示。

    我也再也没有将 ng-if 表达式设置为 false。如果用户不断切换该部分,则保持 DOM 缓存。

    更新: 我在同一个 div 上没有 ng-if 和 ng-show 的原因是在 IE 中它会导致闪烁。当 mouseenter 事件到达时,它会显示内容然后隐藏它。在 chrome 中,可以将它放在同一个 div 上。

    【讨论】:

    • 嗨,这对我的情况来说看起来很棒。我不能在手机上使用 ng-mouseenter 还是可以?有什么选择。
    • 你是对的,在手机或平板电脑上它不会产生任何速度性能。不知道该用什么。
    【解决方案4】:

    您可能对 Alan Colver 的自定义指令 ng-lazy-show 感兴趣。它允许结合ng-ifng-show

    <div ng-lazy-show="showFilters" lendio-business-filters></div>
    

    代码很小,可以很容易地添加到您的项目中:

    var ngLazyShowDirective = ['$animate', function ($animate) {
    
      return {
        multiElement: true,
        transclude: 'element',
        priority: 600,
        terminal: true,
        restrict: 'A',
        link: function ($scope, $element, $attr, $ctrl, $transclude) {
          var loaded;
          $scope.$watch($attr.ngLazyShow, function ngLazyShowWatchAction(value) {
            if (loaded) {
              $animate[value ? 'removeClass' : 'addClass']($element, 'ng-hide');
            }
            else if (value) {
              loaded = true;
              $transclude(function (clone) {
                clone[clone.length++] = document.createComment(' end ngLazyShow: ' + $attr.ngLazyShow + ' ');
                $animate.enter(clone, $element.parent(), $element);
                $element = clone;
              });
            }
          });
        }
      };
    
    }];
    
    angular.module('yourModule').directive('ngLazyShow', ngLazyShowDirective);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-21
      • 2014-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多