将主机属性添加到生成的 DOM 元素

Posted

技术标签:

【中文标题】将主机属性添加到生成的 DOM 元素【英文标题】:Adding host attribute to generated DOM elements 【发布时间】:2016-01-02 04:19:02 【问题描述】:

我正在尝试集成 d3 和 angular2 alpha.37(从 here 开始)。我目前遇到的问题是生成的 DOM 元素没有获得在模拟样式视图封装中使用的属性,因此如果不将元素的视图封装设置为 None (或 Native,但我宁愿使用仿真)。

我设法以编程方式从组件 [1] 内的元素中提取所需的属性,然后将其添加到生成的元素 [2] 中,这确实有效,但这显然是令人难以置信的 hacky:

import Component, View, Attribute, ElementRef, LifecycleEvent from 'angular2/angular2';

import d3 from 'd3';

@Component(
  selector:   'bar-graph',
  properties: [ 'data' ]
)
@View(
  template: '<div class="chart"></div>',
  styles: [`.chart 
    background: #eee;
    padding: 3px;
  

  div.bar 
    width: 0;
    transition: all 1s ease-out;
    -moz-transition: all 1s ease-out;
    -webkit-transition: all 1s ease-out;
  

  div.bar 
    font: 10px sans-serif;
    background-color: steelblue;
    text-align: right;
    padding: 3px;
    margin: 5px;
    color: white;
    box-shadow: 2px 2px 2px #666;
  `]
)
export class BarGraph implements LifecycleEvent.OnChanges 
  data: Array<number>;
  divs: any;
  constructor(elementRef: ElementRef, @Attribute('width') width: string, @Attribute('height') height: string) 


    var el:any    = elementRef.nativeElement;
    var graph:any = d3.select(el);

    this.hostAttr = graph[0][0].children[0].attributes[1].name; //hack here [1]

    this.divs = graph.
      select('div.chart').
      style(
        'width':  width  + 'px',
        'height': height + 'px',
      ).
      selectAll('div.bar');

  

  render(newValue) 
    if (!newValue) return;

    this.divs.data(newValue)
        .enter().append('div')
          .classed('bar', true)
          .attr(this.hostAttr, true) //add the attribute here [2]
          .style('width', d => d + '%')
          .text(d => d + '%');

  

  onChanges() 
    this.render(this.data);
  


有没有推荐的方法来处理这类事情(或者我应该停止修补 Angular2 之外的 DOM)?

【问题讨论】:

如果你想要一个答案,你至少得升级到 beta.0,至少。 @EricMartinez beta.7 上同样的问题。 【参考方案1】:

(还)不是一个完整的答案,但也许有一些有用的信息可以帮助找到解决方案:

这个问题在 beta.8 中仍然存在。将视图封装设置为None 并使用全局样式是我可以开始工作的唯一解决方案。使用Native 似乎根本没有将任何元素添加到DOM,但我必须做更多的测试才能找出原因。 OP 提出的 hack 可行,至少在我看来,可以重构为合理的解决方案。 在 d3.js 的特定情况下,当引入由库内部创建的元素时,事情变得更加棘手,例如通过d3.svg 命名空间中的方法。毫无疑问,也可以找到解决方法。 我相信这个问题比d3 更大。有很多库都有自己的 DOM 生成/操作机制,并且认为其中一部分将在某个时候集成到某个或其他 angular2 应用程序中并非不现实。从这个意义上说,令人惊讶的是这个问题似乎还没有出现(或者我的 Google-fu 这周可能特别弱)。

在解决方案方面,这是我目前正在考虑的两种方法,以防没有人想出更好的方法:

    实现某种后处理器,它遍历部分 DOM 树并设置样式范围属性。也许作为指令? 尝试装饰渲染器,如here 提示的那样。

【讨论】:

以上是关于将主机属性添加到生成的 DOM 元素的主要内容,如果未能解决你的问题,请参考以下文章

使用 CSS 生成的内容(即伪元素)是不是比添加更多 DOM 元素更有效(即解析/渲染更快)?

使用 JavaScript 动态生成 DOM 元素的高效 OOP 方法?

如何在 dom 节点移除、属性修改时添加监听器?

DOM属性操作中CRUD操作

D1.DOM-获取DOM元素、修改属性

添加到 innerHTML 而不破坏表单内容