【问题标题】:Angular 2.x selecting DOM elementAngular 2.x 选择 DOM 元素
【发布时间】:2016-03-29 17:30:06
【问题描述】:

我知道这应该很容易,但 Angular 2.0 还没有很多例子..

在某些情况下,在我的一个组件中,我需要在我的 body 标记上添加类。但是我的应用程序比正文更深入,所以我需要类似的东西

angular.element('body').addClass('fixed');

但在 Angular 2.0..

顺便说一句,我知道我可以以某种方式引导我的应用程序以包含 body 标签,但我认为在其他一些情况下我无论如何都需要选择一些元素,所以我需要一个解决方案来完成这个简单的任务 - “选择元素并为其添加类”

【问题讨论】:

  • angular.element(document.querySelector('body')).addClass('fixed');
  • 但是在 Angular 2.0 中我没有 angular 对象,对吗?
  • document.querySelector('body').className += ' fixed';
  • 组件在理想情况下应该是密封的,它们应该只影响他们自己和他们的孩子。我得到了用例,但请仔细考虑是否绝对必要。

标签: javascript angular typescript


【解决方案1】:

Angular 2 / 4 应用程序中的 DOM 操作

要在 Angular 2/4 应用程序中操作 DOM,我们需要 implement 方法 ngAfterViewInit()AfterViewInit。当第一次检查子指令的绑定时,将调用方法ngAfterViewInit()。换言之,何时最初呈现视图。

@ViewChild 提供对nativeElement 的访问。建议不要访问ngAfterViewInit() 内的nativeElement,因为它不是浏览器安全的。此外,网络工作者也不支持它。 Web Worker 永远不会知道 DOM 何时更新。

正确的方法是使用renderer。渲染器需要注入到组件构造函数中。我们需要为视图上的HTML 元素提供id 引用,如下所示:

<p #p1></p>

应通过相应的组件.ts文件访问,如下所示:


export class SampleComponent implements AfterViewInit {

  @ViewChild("p1") p1;

  constructor(private renderer: Renderer2) //Renderer set to be depreciated soon
  { }

  ngAfterViewInit() {

    //recommended DOM manipulation approach
    this.renderer.setStyle(this.p1.nativeElement, //setElementStyle for soon to be depreciate Renderer
      'color',
      'red');

    //not recommended DOM manipulation approach
    //this.p1.nativeElement.style = "color:blue;";
  }

}

【讨论】:

    【解决方案2】:

    我不建议从 Angular 直接访问 DOM,但您可以通过组件的 ElementRef 获得 DOM 挂钩。一旦您可以访问它,您就可以直接或通过 jquery 或任何其他 DOM 操作技术使用它。我已经包含了一个如何使用 jquery 运行一般查询的示例。如果您总是使用 body 标签,那么您实际上并不需要 ElementRef,但它对于与组件根目录相关的东西很有用。

    import {Component, ElementRef, OnInit} from '@angular/core';
    
    declare var jQuery:any;
    
    @Component({
        selector: 'jquery-integration',
        templateUrl: './components/jquery-integration/jquery-integration.html'
    })
    export class JqueryIntegration implements OnInit {
        elementRef: ElementRef;
    
        constructor(private elementRef: ElementRef) {
        }
    
        ngOnInit() {
            jQuery(this.elementRef.nativeElement).find('.moving-box').draggable({containment:'#draggable-parent'});
        }
    }
    

    更多信息在这里:http://www.syntaxsuccess.com/viewarticle/using-jquery-with-angular-2.0

    演示:http://www.syntaxsuccess.com/angular-2-samples/#/demo/jquery

    【讨论】:

    • 你真的应该尽量不要使用 jQuery。它真的不需要现代 dom 遍历和标准化,而且 ng2 提供了很多浏览器可能不需要的功能
    • @amcdnl 您能否提供一个示例,说明如何访问具有类“.movi​​ng-box”的元素,如上面的代码所示?
    • elementRef.nativeElement.getElementsByClass
    • @juanpastas 如果有样式指南,它怎么没有约定,而且基本上一遍又一遍地重复相同的 3 个文件(html/style/typescript)。试试 Angular CLI,它也会让你的生活更轻松。
    【解决方案3】:

    从 Angular2 版本 2.0.0-beta.17 开始。

    Angular2 中的Attribute Directives 会很好地为您做到这一点。

    请参阅这个用 TypeScript 编写的 plunk。这可以很好地满足您的需求。

    指令文件my-highlight.ts 有一行:

    this.renderer.setElementClass(this.element, "red", true);
    

    这会在元素上设置 CSS 类。

    虽然template.html 具有使用指令[myHighlight] 修饰的实际元素:

    <p [myHighlight]>Mouseover to highlight me!</p>
    

    对我来说,这提供了对问题的最简单的回答,而不依赖于 jqLit​​e。

    【讨论】:

    • 我不明白这与将类添加到 Angulars 根组件之外的元素的问题有什么关系。本教程显示的实际上是不好的做法。另见github.com/angular/angular.io/issues/1670。如果您认为必须使用ElementRef.nativeElement,请与Renderer 一起使用,如stackoverflow.com/a/34573219/217408 所示,而不是直接在其上调用方法。
    • 感谢您使用渲染器链接到另一篇文章,这看起来很有趣。我将使用最新的 Angular2 文档,如果发生变化,我将更新我的 plunk。我仍然觉得这是一个很好的答案,因为问题表明他们想要“选择元素并为其添加类”。我将更新我的答案以编辑“类”属性而不是“样式”。
    • 在我看来它仍然不适合这个问题,因为它不允许在 &lt;body&gt; 元素上设置属性。不过,这从问题中并不太明显。
    • 是的,我现在在问题中看到了正文标签。我认为我的回答可能会帮助那些想要选择任何其他 DOM 元素的人。
    • 我已更新我的答案以更改 CSS 类。我也添加了渲染器来执行此操作。我非常想把这个答案留在这里,因为正是这个特定的问题把我带到了这里,我相信其他人可能会觉得这很有用。
    【解决方案4】:

    更新

    我不确定DOM 是否仍然在 RC 中受支持。相关说法不是很清楚。像

    DOM 仅供内部使用。直接访问 DOM 或使用自定义渲染器。

    我还没有看到如何实现自定义渲染器或如何根据当前平台(webworker、服务器、DOM 线程)提供实现。

    更新 这似乎是Angular2的方式

    import { DOM } from 'angular2/src/platform/dom/dom_adapter';
    
    DOM.addClass(DOM.query("body"), 'fixed');
    

    .../src/... 导入,风险自负。 .../src/... 被认为是私有实现,您不能期望任何保证 API 不会在没有通知的情况下更改。

    我在 Dart 中尝试过,它工作正常(但不确定上面的 TS 导入是否正确)。在 Dart 中 DOMpackage:angular2/angular2.dart 导出

    原创

    如果您想访问 Angular 应用程序根目录之外的 DOM 元素,只需使用 document.querySelector(),无需涉及 Angular。

    【讨论】:

    • 但是 angular 1.x 有 jquery lite 或其他东西来帮助添加/删除类。 Angular 2.0 是否有类似 jqlite 的东西来帮助为应用程序根目录之外的元素添加/删除类?
    • 我不这么认为。 Angular2 旨在避免直接 DOM 访问,以确保一切都与 webworkers 和服务器端渲染一起工作。
    • 感谢您的提示。我最终做了以下事情:ngOnInit() { var dom = new BrowserDomAdapter(); dom.addClass(dom.query("body"), "login-content"); } ngOnDestroy() { var dom = new BrowserDomAdapter(); dom.removeClass(dom.query("body"), "login-content"); }
    • 在 beta7 中,导入现在是 import { BrowserDomAdapter } from 'angular2/platform/browser'; 在此处查看可用方法:angular.io/docs/ts/latest/api/platform/browser/…
    【解决方案5】:

    angular 2.4 开始,您应该注入DOCUMENT 并且不要与任何适配器交互:

    import { Component, Inject } from '@angular/core';
    import { DOCUMENT } from '@angular/platform-browser';
    
    @Component({})
    export class MyClass {
    
        constructor (@Inject(DOCUMENT) private document) { }
    
        doSomething() {
            this.document.someMethodOfDocument();
        }
    }
    

    延伸阅读:https://github.com/angular/angular/issues/8509

    【讨论】:

      猜你喜欢
      • 2017-05-16
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-27
      • 2019-02-27
      • 2019-12-21
      相关资源
      最近更新 更多