具有范围的 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 指令是否可行。我想您可以使用组件(使用属性选择器)和模板元素来做一些事情。像这样的东西:<div foo><template>something</template></div>
。这个答案可以给你一些想法:***.com/questions/36531503/….
@ThierryTemplier 你的 标签提示给了我尝试类似 *foo 的想法。我想我必须看看 *ngFor 是如何制作的——它有一些局部变量(如索引、偶数、奇数)。谢谢你的提示【参考方案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 指令的主要内容,如果未能解决你的问题,请参考以下文章