Angular2-私有变量是否可以在模板中访问?

如果一个变量在一个组件类上声明为 private,我是否应该能够在该组件的模板中访问它?

@Component({
selector: 'my-app',
template: `
<div>
<h2>{{title}}</h2>
<h2>Hello {{userName}}</h2> // I am getting this name
</div>
`,
})
export class App {
public title = 'Angular 2';
private userName = "Test Name"; //declared as private
}
77731 次浏览

编辑: 这个答案现在是不正确的。当我发布这篇文章的时候,并没有官方的指导,但是在@Yaroslov 的回答中解释说,情况已经不再是这样了: Codelizer 现在发出警告,AoT 编译在引用组件模板中的私有变量时会失败。也就是说,在概念层面上,这里的一切都是有效的,所以我将留下这个答案,因为它似乎是有帮助的。


是的,这是意料之中的。

请记住,private和其他访问修饰符是类型脚本构造,而 Component/controller/template 是类型脚本一无所知的角度构造。访问修饰符控制可见性 中间类: 使字段 private阻止 其他课程访问它,但模板和控制器是存在 内心类的东西。

这在技术上并不正确,但是(代替理解类如何与装饰器及其元数据相关) ,这样想可能会有帮助,因为重要的事情(IMHO)是从把模板和控制器看作独立的实体转变为把它们看作组件构造的统一部分——这是 ng2心智模型的主要方面之一。

从这个角度考虑,显然我们希望组件类的 private变量在其模板中可见,出于同样的原因,我们希望它们在该类的 private方法中可见。

尽管代码示例表明问题是关于 TypeScript 的,但它没有 标记。Angular2也可用于达特,这是一个显着的差异,达特。

飞镖中,组件类的 模板不能引用私有变量,因为 Dart 与 TypeScript 形成对比,有效地阻止从外部访问私有成员。

我仍然支持@drewmoores 的建议,认为组件和它的模板作为一个单位,虽然。

更新(TS) 在 Angular2 TS 以及 href = “ https://github.com/angle/angle/questions/11422”https://github.com/angular/angular/issues/11422中,离线编译访问私有财产似乎将变得更加有限

UPD

从角度14开始,就是 有可能绑定模板中的 protected组件成员。这应该部分地解决了将内部状态(应该只对模板可访问)作为组件的公共 API 公开的问题。


不,您不应该在模板中使用私有变量。

虽然我喜欢 Drewmoore 的回答,并且认为它具有完美的概念逻辑,但在实现方面它是错误的。模板不存在于组件类中,而是存在于组件类之外。看看 这个回购的证据。

它工作的唯一原因是因为 TypeScript 的 private关键字并不真正使成员私有。即时编译在运行时发生在浏览器中,而且 JS 还没有任何私有成员的概念(到现在为止?).感谢 Sander Elias让我走上了正确的道路。

使用 ngc和 Ahead-of-Time 编译,如果尝试从模板访问组件的私有成员,将会得到错误。克隆演示回购,改变 MyComponent成员的可见性私有和你会得到编译错误,当运行 ngc。这里还提供了专门用于提前编译的 回答

可以在组件的模板中使用私有变量。参见 angular2备忘录的指南: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-child-setter

在这里可以找到关于类的 public/private 成员的更详细的解释: https://www.typescriptlang.org/docs/handbook/classes.html

默认情况下,所有成员都是 Public。可以从组件类以及类实例外部访问公共成员。但是只能在类成员函数中访问私有成员。

解决方案可以在其文件中使用私有变量并使用 getter。

private _userName = "Test Name";
get userName() {
return this._userName;
}

这是一种很好的方法,因为 ts 文件和 html 保持独立。即使在 ts 文件中更改了 _ userName 变量名,也不必在模板文件中进行任何更改。

简短的回答是否定的,您不应该能够从模板访问私有成员,因为它在技术上与 TS 文件分离。

在 tsconfig.app.json 中,如果您在编译器选项中提供“ fullTemplateTypeCheck”选项,那么您可以在项目构建时看到项目的 html 文件中的所有无效引用。

"angularCompilerOptions": {
"enableIvy": true,
"fullTemplateTypeCheck": true

}

我知道这有点晚了,但是我从 Angular2开始就一直在关注这个问题,最后我想出了一个不错的解决方案,让我能够拥有合适的 API 组件,也能够通过合适的类型检查从模板中访问私有字段:

export interface MyComponentPrivateProperties {
_label: string;
}
export class MyComponent {
private _label: string = 'Label';


public get view(): MyComponentPrivateProperties {
return this as any;
}
}
<div>\{\{view._label}}</div>

通过这种方式,您可以看到,我们甚至可以进行类型检查,所有我们需要的都在 html 模板中,还有组件的适当 API。如果在另一个组件中,我们像下面这样引用 MyComponent类:

export class OtherComponent {
private _m: MyComponent;


ngOnInit() {
// here, this._label is not visible.
}
}

我们将注意到属性 _label是不可见的。

当然,请注意类 MyComponent不应该实现接口 MyComponentPrivateProperties。这个接口没有实现。这只是对角 ngc编译器的描述。它在编译时告诉编译器哪些私有属性应该可以从模板访问,然后在运行时消失。