想象一下可能在网页上呈现的一些繁重的内容,例如图表。 Angular提供2个选项来切换所述内容的可见性。
无论表达式如何,ng-show 都会呈现内容,并在事后简单地“隐藏”它。这并不理想,因为用户可能永远不会在会话期间“打开”内容,因此渲染它是一种浪费。
ng-if 在这方面更好。如果表达式为false,使用它代替ng-show将防止重型内容首先呈现。然而,它的优势也是它的弱点,因为如果用户隐藏图表然后再次显示它,则每次都会从头开始呈现内容。
如何制定充分利用这两个方面的指令?这意味着它就像ng-if直到第一次呈现内容一样,然后切换到像ng-show一样的工作,以防止每次都重新呈现它。
答案 0 :(得分:20)
+1对丹尼斯的回答,但为了完整起见,甚至可以通过将逻辑保持在视图中而不用"污染"来进一步简化它。控制器:
<button ng-click="show = !show">toggle</button>
<div ng-if="once = once || show" ng-show="show">Heavy content</div>
编辑:通过一次性绑定可以进一步改进(和简化)以上版本,以减少once
上不必要的$ watch - 这只适用于Angular 1.3+:
<div ng-if="::show || undefined" ng-show="show">Heavy content</div>
需要undefined
以确保观看的值在变为true
之前不会"stabilize"。一旦稳定,它也会失去$ watch,因此不会受到show
的任何进一步更改的影响。
答案 1 :(得分:9)
您可以将ngIf
和ngShow
放在一起使其工作,其中每个控件都由不同的变量控制。 ngIf
将被设置为true
一次,并且永远不会再设置为false
,而ngShow
将会根据用户的需要进行切换。
看看这个fiddle。
答案 2 :(得分:5)
@ new-dev的回答启发了我自己的组合想法,使用切换按钮快速获得非常重的组件。
我最初的问题是我的页面包含~20个组件,每个组件需要大约1秒钟才能加载。每个人都被一个按钮切换。
如果使用普通ng - 如果我将在切换按钮后立即加载页面并延迟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上。
答案 3 :(得分:0)
您可能对Alan Colver的自定义指令ng-lazy-show
感兴趣。它允许合并ng-if
和ng-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);