具有范围的 Angular2 指令

Posted

技术标签:

【中文标题】具有范围的 Angular2 指令【英文标题】:Angular2 Directive with scope 【发布时间】:2016-09-13 19:55:39 【问题描述】:

Angular2 中的指令没有“范围”,而组件有。但就我而言,我需要 Directive 来创建范围。看看我的 App 组件——它有一个 html 模板,并且在任何元素上的任何地方都可能出现 foo 指令。这应该从服务中获取一些日期并将其分配给元素。

在 Angular1 中这很容易......指令可以有自己的范围。但在 Angular 2 中,我找不到任何(甚至是肮脏的)方法来实现这一点。

这看起来很简单,不是吗?

@Directive(
  selector: '[foo]'
)
class FooDirective 
  @Input()
  public id:string;

  public bar;

  constructor() 
     this.bar = 'This is the "bar" I actually need. It is taken from DB let's say..' + this.id;
  





@Component(
  selector: 'app',
  template: `
     <div foo id="2">
       This is random content 1: bar
     </div>

     <div foo id="2">
       This is random content 2: bar
     </div>
  `,
  directives: [FooDirective]
)
class App 
  bar:string = 'This should be ignored, I need "bar" to be set from directive!';


bootstrap(App);

【问题讨论】:

【参考方案1】:

您可以尝试利用引用应用指令的局部变量来进行类似的操作:

@Component(
  selector: 'app'
  template: `
    <div foo id="2" #dir1="foo">
      This is random content 1: dir1.bar
    </div>

    <div foo id="2" #dir2="foo">
      This is random content 2: dir2.bar
    </div>
  `,
  directives: [FooDirective]
)
class App 
  bar:string = 'This should be ignored, I need "bar" to be set from directive!';

在您的情况下,bar 是使用当前组件的属性评估的,App 之一。

编辑(在@yurzui 的评论之后)

您需要在指令中添加exportAs 属性:

@Directive(
  selector: '[foo]',
  exportAs: 'foo'
)
class FooDirective 
  (...)

【讨论】:

是的,我知道。但是假设我正在为我们的设计师创建“帮助”指令,我说他们“在任何元素上添加 foo,它会从数据库中获取一些数据”。我不需要添加“额外的工作”他们..(我已经用 angular 1 完成了这个工具,所以他们不会喜欢我的“为他们做更多工作”的新工具 不要忘记在元数据指令中添加 exportAs: 'foo'。 另外,我认为那些“局部变量”的一个模板是有限制的。但是我们的模板很大 我很理解你的做法!也就是说,我不确定 Angular2 指令是否可行。我想您可以使用组件(使用属性选择器)和模板元素来做一些事情。像这样的东西:&lt;div foo&gt;&lt;template&gt;something&lt;/template&gt;&lt;/div&gt;。这个答案可以给你一些想法:***.com/questions/36531503/…. @ThierryTemplier 你的 【参考方案2】:

你说组件确实有作用域是什么意思?

我的理解是组件之间没有共享对象(或原型继承)。但是我认为这就是您要寻找的东西-您希望 FooDirective 和 App 共享相同的(范围)对象,对吗?如果是这样,我认为 Angular 2 中没有任何等价物。


我怀疑你会喜欢这个,但我能想到的最好的方法(这与 @Thierry 的方法不同)是使用 div 作为“共享对象”(而不是指令)。该指令使用 HostBinding 将值保存到 div 上的数据属性,然后组件在模板中检索该值,使用局部变量获取对 div/shared 对象的引用:

import Component, Directive, Input, HostBinding from '@angular/core';

@Directive(selector: '[foo]')
class FooDirective 
  @Input() id:string;
  @HostBinding('attr.data-bar') bar;
  ngOnInit() 
     this.bar = 'This is "bar" I actually need. It is taken from DB lets say...' + this.id;
  


@Component(
  selector: 'my-app',
  template: `title<p>
    <div #div1 foo id="2">
      This is random content 1: div1.getAttribute('data-bar')
    </div>`,
  directives: [FooDirective]
)
export class AppComponent 
  title = `Angular - RC.1`;

Plunker

我喜欢@Thierry 的方法比我上面展示的更好,但我想我还是会发布我正在玩弄的东西。

【讨论】:

感谢您的回答,但我仍然努力为我的公司设计师减少“工作量”。我的意思是他们已经在使用我来自 Angular 1 的指令,我说他们“在任何元素上添加'foo',你将在bar 中获得一些魔法值”。我不能对他们说“我已经用 Angular 2 制作了更好的工具,但现在你必须添加更多的工作才能获得相同的结果......”而且我仍然相信用 Angular 2 制作它是可能的。在我正在尝试使用结构指令 (*foo)

以上是关于具有范围的 Angular2 指令的主要内容,如果未能解决你的问题,请参考以下文章

具有多个子组件实例的Angular2父组件

如何使指令和组件在全球范围内可用

Angular2更新指令输入

从属性到结构,带你深入理解 Angular2 两大类型指令!

angular2 自定义指令输入语法

Angular2 指令监听父组件回调或更改