22

在这里尝试使用 Angular 2 ......明白它仍处于 alpha 阶段。

如何从组件访问 DOM 元素?具体来说,我想使用d3等其他库从代码生成自定义 DOM。我想我需要创建一个组件并以某种方式插入组件生命周期以使用 d3 更改 DOM ...知道从哪里开始挖掘吗?

我正在使用这个快速入门回购

谢谢!

4

5 回答 5

19

如果您不介意使用 Directive 而不是 Component,那很简单。对于 typescript 中的 Angular 2.0.0-alpha.33,您可以使用 D3 通过注入 ElementRef 来操作 DOM:

@Directive({
    selector:   'scatter-plot',
    lifecycle: [LifecycleEvent.onChange],
    properties: [ 'data' ]
})
export class ScatterPlot {

    root: Selection<any>;
    data: Array<ScatterPlotDataPoint>;

    x: (number) => number;
    y: (number) => number;

    defaultSize: string;
    circles: any;

    constructor(
        @Inject(ElementRef) elementRef: ElementRef,
        @Attribute('height') height: string,
        @Attribute('default-size') defaultSize: string
    ) {
        var el:HTMLElement = elementRef.nativeElement;
        this.root = d3.select(el);

        this.defaultSize = defaultSize ? defaultSize : "5";
        this.circles = this.root
            .append('svg')
            .attr('class', 'chart')
            .style({
                'width':  '100%',
                'height': height ? height + 'px': '',
            }).
            selectAll('circle');

    }

    render(newValue) {
        if (!newValue) return;

        this.x = d3.scale.linear().domain([-10, 110]).range([0, 250]);
        this.y = d3.scale.linear().domain([-10, 110]).range([100, 0]);

        this.circles = this.circles
            .data(newValue);

        this.circles.exit().remove();

        this.circles.enter()
            .append('circle');

        this.circles
            .transition()
            .attr("r", d => d.size ? d.size: this.defaultSize)
            .style("fill", d => d.color)
            .attr('cx', d => this.x(d.x))
            .attr('cy', d => this.y(d.y));

    }

    onChange() {
        this.render(this.data);
    }
}
于 2015-08-18T01:12:36.947 回答
7

使用 ElementRef

ElementRef 会将当前的 DOM 节点注入到您的组件中。ElementRef 服务将始终位于当前 DOM 节点的本地。

注入后,您可以使用 nativeElement 获取实际的 DOM 节点:

var el = elementRef.nativeElement

一旦你有了这个,你可以用任何你喜欢的方式来操作它,或者使用 DOM 脚本,或者使用像 jQuery 这样的 DOM 包装器:

$(el)
  .append('<p>Some interesting Stuff')
  .addClass('my_class');

但如果你能帮助它,请不要这样做

请注意,与 Angular 1 一样,不鼓励使用直接 DOM 操作。您可以使用模板完成几乎所有的工作,并且您应该在大多数情况下支持这种工作方式。

直接的 DOM 操作会导致代码复杂、难以理解、难以测试。

不过,有时它似乎是最好的解决方案。例如,如果您必须与第三方、高度复杂的框架(如图形库)集成。

这是一个工作示例(在 ES6 中)

var AppComponent = ng.core
  .Component({
    selector: "app",
    template:
    `
      <div>Captured element</div>
    `
  })
  .Class({
    constructor: [ng.core.ElementRef, function(elementRef) {
      var el = elementRef.nativeElement
      el;
    }]
  })
于 2016-02-27T18:15:17.680 回答
5

注意:[已弃用]

您可以使用“BrowserDomAdapter”
https://angular.io/docs/ts/latest/api/platform/browser/BrowserDomAdapter-class.html

import {BrowserDomAdapter} from 'angular2/platform/browser'

@Component({
  selector: 'dom',
  templateUrl: 'path/to/template.html',
  providers: [BrowserDomAdapter]
})
export class DomComponent {
  constructor(private _dom: BrowserDomAdapter) {
    var domIWant = this._dom.query('whatever you want to get');
  }
}

过程

  1. 导入 BrowserDomAdapter
  2. 应用提供者:[BrowserDomAdapter]
  3. 在构造函数()中启动
  4. 使用实例化 BrowserDomAdapter 获取 dom
于 2016-01-25T08:58:47.377 回答
0

该文档(http://victorsavkin.com/post/118372404541/the-core-concepts-of-angular-2)提到了“装饰器样式指令”,我相信这里有更多详细信息和基本示例(https ://angular.io/api/core/Directive)。

于 2015-05-11T12:34:54.607 回答
0

正如其他海报所提到的:您可以通过注入ElementRef指令来操作 DOM。但是,请仔细考虑您是否真的要这样做。

D3 是一个 DOM 操作工具。它允许您将数据对象绑定到 DOM 节点,然后从该元素添加或删除子元素以响应更改的数据值。这几乎正​​是 Angular 2 所做的。

当然,D3 还可以做其他事情。例如,您可以为饼图或正态分布生成角度,您可能希望为此使用 D3。

我知道这不是你要找的答案。这不是我要寻找的答案,但是...仔细考虑是否需要使用 D3 进行 DOM 操作和数据绑定。Angular 2 已经有了 DOM 操作和数据绑定。

于 2016-09-01T11:38:11.430 回答