【问题标题】:What is the equivalent of ngShow and ngHide in Angular 2+?Angular 2+ 中 ngShow 和 ngHide 的等价物是什么?
【发布时间】:2016-06-05 07:43:51
【问题描述】:

我有一些元素希望在特定条件下可见。

我会在 AngularJS 中编写

<div ng-show="myVar">stuff</div>

如何在 Angular 2+ 中做到这一点?

【问题讨论】:

  • [hidden]="!myVar".. 这适用于角度 2+

标签: angular angular-components angular-template


【解决方案1】:

hidden 属性可用于此

[hidden]="!myVar"

另见

问题

hidden 有一些问题,因为它可能与 display 属性的 CSS 冲突。

看看Plunker example 中的some 是如何隐藏的,因为它有一个样式

:host {display: block;}

设置。 (这可能在其他浏览器中表现不同 - 我使用 Chrome 50 进行了测试)

解决方法

你可以通过添加来修复它

[hidden] { display: none !important;}

index.html 中的全局样式。

另一个陷阱

hidden="false"
hidden="{{false}}"
hidden="{{isHidden}}" // isHidden = false;

相同
hidden="true"

并且不会显示元素。

hidden="false" 将分配字符串"false",这被认为是真实的。
只有值 false 或删除属性才会真正使元素 可见。

使用{{}} 也会将表达式转换为字符串,并且不会按预期工作。

只有与[] 绑定才能按预期工作,因为此false 被分配为false 而不是"false"

*ngIf[hidden]

*ngIf 有效地将其内容从 DOM 中删除,而 [hidden] 修改了 display 属性并仅指示浏览器不显示内容,但 DOM 仍然包含它。

【讨论】:

  • *ngIf 在大多数情况下可能是正确的方式,但有时您实际上希望一个元素存在,视觉上隐藏。带有[hidden]{display:none!important} 的 CSS 样式会有所帮助。例如,Bootstrap 如何确保 [hidden] 元素实际上是隐藏的。 See GitHub
  • 在 *ngIf 中使用 (myStream | async) 管道时可能会遇到一些问题,而 *ngIf 也使用 (myStream | async) 管道
  • 你是我的救星!使用 *ngIf 会将 DOM 位置重置为顶部,但 [hidden] 解决了我的问题并保留了位置。
  • 当您使用 HostListener(并且想要区分文档点击与 event.target)时,可能想要使用 [hidden] 而不是 *ngIf 的一种情况,当您尝试显示和隐藏元素(如带有自定义下拉菜单)
  • @Sam,您的评论具有误导性。是的,hidden 有一些特殊之处。但是根据链接的文章说Using hidden is actually not recommended.是错误的。
【解决方案2】:

使用ngIf 处理此问题的最佳方法 因为这会阻止该元素在前端呈现,

如果您使用[hidden]="true" 或样式隐藏[style.display] 它只会隐藏前端的元素,并且有人可以更改它的值并轻松查看它, 我认为隐藏元素的最佳方式是ngIf

<div *ngIf="myVar">stuff</div>

如果你有多个元素(也需要实现 else),你可以使用 &lt;ng-template&gt; 选项

<ng-container *ngIf="myVar; then loadAdmin else loadMenu"></ng-container>
<ng-template #loadMenu>
     <div>loadMenu</div>
</ng-template>

<ng-template #loadAdmin>
     <div>loadAdmin</div>
</ng-template>  

sample ng-template code

【讨论】:

  • 我同意你的观点,出于某些性能原因,最好使用 *ngIf 而不是 hidden 来进行 DOM 优化
【解决方案3】:

在 Angular 6 中单击按钮时隐藏和显示 div。

HTML 代码

<button (click)="toggleElement()">FormatCell</button>
<div class="ruleOptionsPanel" *ngIf="isShow">
   <table>
      <tr>
         <td>Name</td>
         <td>Ram</td>
      </tr>
   </table>
</div>

AppComponent.ts 代码

@Component({
   selector: 'app-root',
   templateUrl: './app.component.html',
   styleUrls: ['./app.component.css']
})
export class AppComponent{
   isShow=false;
   toggleElement():void
   {
      this.isShow = !this.isShow
   }
}

这对我有用,它是一种在 angular2+ 中替换 ng-hide 和 ng-show 的方法

【讨论】:

  • 您正在使用 ngIf - 这与 ngShow 不同。 NgIf 将从 DOM 中删除/添加元素。这与 ngShow/ngHide 不同,后者只会向元素添加/删除 Css 样式。
  • 例子太长太具体了。
【解决方案4】:

您有两种选择:

第一个选项

[style.display]="!isShow ? 'block' : 'none'"

第二个选项

myVarible 可以是布尔值

[hidden]="!myVarible"

【讨论】:

    【解决方案5】:

    我的问题是在单击按钮时显示/隐藏垫表 。表的“加载”速度非常慢,2-3 秒内有 300 条记录。

    数据是使用 ngOnInit() 中的订阅加载的,并且可以在模板中使用并准备好使用,但是随着行数的增加,模板中表格的“加载”变得越来越慢。

    我的解决方案是将 *ngIf 替换为:

    &lt;div [style.display]="activeSelected ? 'block' : 'none'"&gt;

    。 现在点击按钮时表格会立即加载。

    【讨论】:

      【解决方案6】:

      这对我有用:

      <div [style.visibility]="showThis ? 'visible' : 'hidden'">blah</div>
      

      【讨论】:

        【解决方案7】:

        如果你只想使用 AngularJS 自带的对称 hidden/shown 指令,我建议编写一个属性指令来简化模板,像这样(使用 Angular 7 测试):

        
        import { Directive, Input, HostBinding } from '@angular/core';
        
        @Directive({ selector: '[shown]' })
        export class ShownDirective {
          @Input() public shown: boolean;
        
          @HostBinding('attr.hidden')
          public get attrHidden(): string | null {
            return this.shown ? null : 'hidden';
          }
        }
        

        许多其他解决方案都是正确的。您应该尽可能使用*ngIf。使用hidden 属性可以应用意想不到的样式,但除非您正在为其他人编写组件,否则您可能知道是否是这样。因此,要让这个 shown 指令起作用,您还需要确保添加:

        [hidden]: {
          display: none !important;
        }
        

        到某个地方的全局样式。

        有了这些,你可以像这样使用指令:

        <div [shown]="myVar">stuff</div>
        

        像这样的对称(和相反)版本:

        <div [hidden]="myVar">stuff</div>
        

        要添加到 应该 - 你也应该使用像 [acmeShown] 这样的前缀而不是 [shown]

        我使用shown 属性指令的主要原因是当隐藏的内容包含导致 XHR 往返的容器组件时,将 AngularJS 代码转换为 Angular -AND-。我不只是使用[hidden]="!myVar" 的原因是它通常更复杂,例如:[hidden]="!(myVar || yourVar) &amp;&amp; anotherVar" - yes I can invert that, but it is more error prone.[shown]` 更容易思考。

        【讨论】:

          【解决方案8】:

          对我来说,[hidden]=!var 从来没有用过。

          所以,&lt;div *ngIf="expression" style="display:none;"&gt;

          而且,&lt;div *ngIf="expression"&gt; 总是给出正确的结果。

          【讨论】:

            【解决方案9】:
            <div [hidden]="myExpression">
            

            myExpression 可以设置为 true 或 false

            【讨论】:

            • &lt;div hidden="{{ myExpression }}"&gt; 这不起作用,因为“myExpression”将被转换为要在 html 中呈现的字符串。字符串 "true" 和 "false" 都是真值,所以它会一直隐藏
            • @Viprus 不是在挑剔你,但我以前在这里看到过这种对“真实”一词的误用。如果 CSS 选择器是 [hidden],并且该属性存在于 HTML 中并且具有值,则将应用该规则。在这种情况下,真实性并不重要,因为它不是 JS。
            【解决方案10】:

            使用[hidden] 属性:

            [hidden]="!myVar"
            

            或者你可以使用*ngIf

            *ngIf="myVar"
            

            这是显示/隐藏元素的两种方式。唯一的区别是:*ngIf 将从 DOM 中删除元素,而 [hidden] 将告诉浏览器使用 CSS display 属性显示/隐藏元素,方法是将元素保留在 DOM 中。

            【讨论】:

            • [hidden] 正在向元素添加有条件的“隐藏”属性。它也可以是 [whatever] 或 [ali]。这里重要的是加载一个提到“隐藏”属性的 CSS 规则必须是 display:none
            • 请记住:*ngIf 和 [hidden] 是根本不同的。在条件为真之前,ngIf 不会评估 *ngIf 块内的内容。如果您使用 async 管道,这一点尤其重要,因为只有在条件变为 true 后才会添加对 observable 的订阅!
            • 要考虑的另一件事是 *ngIf 会破坏组件并且必须重新创建它,而 [hidden] 使其保持活动状态并保留在内存中。如果你有一个资源密集型组件,最好隐藏它而不是销毁它
            • 它们不是一回事。
            • 如前所述,完全不一样。如果一个组件正在使用ngIf 并且结果为假,则它根本不会被渲染,因此组件内的任何代码都不会运行,直到满足ngIf 条件。
            【解决方案11】:

            Angular 文档上有两个例子https://angular.io/guide/structural-directives#why-remove-rather-than-hide

            指令可以通过将其显示样式设置为无来隐藏不需要的段落。

            <p [style.display]="'block'">
              Expression sets display to "block".
              This paragraph is visible.
            </p>
            
            <p [style.display]="'none'">
              Expression sets display to "none".
              This paragraph is hidden but still in the DOM.
            </p>
            

            您可以使用 [style.display]="'block'" 替换 ngShow 和 [style.display]="'none'" 替换 ngHide。

            【讨论】:

              【解决方案12】:
              <div [hidden]="flagValue">
              ---content---
              </div>
              

              【讨论】:

                【解决方案13】:

                我发现自己的情况与我的情况不同,元素是一个弹性容器。如果不是你的情况,一个简单的解决方法可能是

                [style.display]="!isLoading ? 'block' : 'none'"
                

                在我的情况下,由于我们支持的许多浏览器仍然需要供应商前缀以避免出现问题,所以我选择了另一个简单的解决方案

                [class.is-loading]="isLoading"
                

                那么 CSS 就这么简单

                &.is-loading { display: none } 
                

                然后离开由默认类处理的显示状态。

                【讨论】:

                • 这适用于 bootstrap 4 invalid-feedback 类。
                【解决方案14】:

                对于其他遇到此问题的人来说,这就是我完成它的方法。

                import {Directive, ElementRef, Input, OnChanges, Renderer2} from "@angular/core";
                
                @Directive({
                  selector: '[hide]'
                })
                export class HideDirective implements OnChanges {
                  @Input() hide: boolean;
                
                  constructor(private renderer: Renderer2, private elRef: ElementRef) {}
                
                  ngOnChanges() {
                    if (this.hide) {
                      this.renderer.setStyle(this.elRef.nativeElement, 'visibility', 'hidden');
                    } else {
                      this.renderer.setStyle(this.elRef.nativeElement, 'visibility', 'visible');
                    }
                  }
                }
                

                我使用'visibility' 是因为我想保留元素占用的空间。如果您不想这样做,您可以使用'display' 并将其设置为'none';

                您可以将其绑定到您的 html 元素,无论是否动态。

                <span hide="true"></span>
                

                <span [hide]="anyBooleanExpression"></span>
                

                【讨论】:

                • 这似乎是最“Angular”的方式。
                【解决方案15】:

                在 bootstrap 4.0 中,类 "d-none" = "display: none!important;"

                <div [ngClass]="{'d-none': exp}"> </div>
                

                【讨论】:

                  【解决方案16】:

                  如果你使用Bootstrap就这么简单:

                  <div [class.hidden]="myBooleanValue"></div>
                  

                  【讨论】:

                  • 在 bootstrap 4 中使用 [hidden] 做同样的事情,所以我推荐 [hidden]
                  【解决方案17】:

                  对不起,我不同意在使用 Angular 2 时绑定到被认为不安全的 hidden。这是因为隐藏样式可以很容易地被覆盖,例如使用

                  display: flex;
                  

                  推荐的方法是使用*ngIf,这样更安全。更多详细信息,请参考 Angular 官方博客。 5 Rookie Mistakes to Avoid with Angular 2

                  <div *ngIf="showGreeting">
                     Hello, there!
                  </div>
                  

                  【讨论】:

                  • 我认为在了解确切要求之前说某事不好是一个新手错误。如果不想删除和销毁、添加和重新创建元素,*ngIf 是一个糟糕的选择。但你说得对,需要考虑后果,指出陷阱总是一个好主意。
                  • 我知道你的意思。这不是我的话,这是一个新手错误,它来自 Angular 2 官方博客。我无意冒犯任何人。不过,感谢您指出。
                  • 是的,我不认为ngIf 完全回答了这个问题。我想在包含&lt;router-outlet&gt; 的页面上隐藏一些内容。如果我使用ngIf,我会收到找不到插座的错误消息。我需要将插座 隐藏 直到我的数据加载,而不是 absent 直到我的数据加载。
                  • 我同意你的看法,但我遇到的问题是,如果我使用 *ngIf,我想显示一个表单并将值放入其中,我将遇到未定义的错误,并且使用隐藏的属性它运行良好
                  • @HazemHASAN,当然。我明白。解决方案总是有条件的。在您的情况下,不确定是否可以在针对它运行任何其他代码之前检查表单是否存在。这都是关于权衡的。您是否想要一种更安全的方法来隐藏将来不会被其他样式意外抵消的表单?还是您更喜欢方便不检查表单是否存在?
                  【解决方案18】:

                  根据 ngShowngHide 的 Angular 1 文档,这两个指令都根据该指令的条件将 css 样式 display: none !important; 添加到元素(对于 ngShow 将 css 添加到 false 值,并且for ngHide 将 css 添加为 true 值)。

                  我们可以使用 Angular 2 指令 ngClass 来实现这种行为:

                  /* style.css */
                  .hide 
                  {
                      display: none !important;
                  }
                  
                  <!-- old angular1 ngShow -->
                  <div ng-show="ngShowVal"> I'm Angular1 ngShow... </div>
                  
                  <!-- become new angular2 ngClass -->
                  <div [ngClass]="{ 'hide': !ngShowVal }"> I'm Angular2 ngShow... </div>
                  
                  <!-- old angular2 ngHide -->
                  <div ng-hide="ngHideVal"> I'm Angular1 ngHide... </div>
                  
                  <!-- become new angular2 ngClass -->
                  <div [ngClass]="{ 'hide': ngHideVal }"> I'm Angular2 ngHide... </div>
                  

                  请注意,对于 Angular2 中的 show 行为,我们需要在 ngShowVal 之前添加 !(不是),对于 Angular2 中的 hide 行为,我们不需要需要添加 @987654328 @(不是)在 ngHideVal 之前。

                  【讨论】:

                    【解决方案19】:

                    使用 hidden 就像将任何 model 绑定到控件并为其指定 css

                    HTML:

                    <input type="button" class="view form-control" value="View" [hidden]="true" />
                    

                    CSS:

                    [hidden] {
                       display: none;
                    }
                    

                    【讨论】:

                      【解决方案20】:

                      如果您的情况是样式为无显示,您也可以使用 ngStyle 指令并直接修改显示,我这样做是为了引导 DropDown,将其上的 UL 设置为无显示。

                      所以我创建了一个点击事件来“手动”切换 UL 以显示

                      <div class="dropdown">
                          <button class="btn btn-default" (click)="manualtoggle()"  id="dropdownMenu1" >
                          Seleccione una Ubicación
                          <span class="caret"></span>
                          </button>
                          <ul class="dropdown-menu" [ngStyle]="{display:displayddl}">
                              <li *ngFor="let object of Array" (click)="selectLocation(location)">{{object.Value}}</li>                                
                           </ul>
                       </div>    
                      

                      然后在组件上我有 showDropDown:bool 属性,我每次都切换,并基于 int,为样式设置 displayDDL,如下所示

                      showDropDown:boolean;
                      displayddl:string;
                      manualtoggle(){
                          this.showDropDown = !this.showDropDown;
                          this.displayddl = this.showDropDown ? "inline" : "none";
                      }
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2018-06-17
                        • 2016-11-02
                        • 2016-05-19
                        • 1970-01-01
                        • 1970-01-01
                        • 2014-10-09
                        • 2019-12-23
                        • 2016-04-06
                        相关资源
                        最近更新 更多