158

如果在组件类上声明了一个变量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
}
4

8 回答 8

243

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

虽然我喜欢drawmoore 的回答并在其中看到完美的概念逻辑,但在实施方面它是错误的。模板不存在于组件类中,而是存在于它们之外。看看这个 repo以获得证明。

它起作用的唯一原因是 TypeScript 的private关键字并没有真正将成员设为私有。即时编译发生在运行时的浏览器中,而 JS 没有任何私有成员的概念(还没有?)。归功于Sander Elias让我走上了正轨。

使用ngc和 Ahead-of-Time 编译,如果您尝试从模板访问组件的私有成员,您将收到错误。克隆演示仓库,将MyComponent成员的可见性更改为私有,运行时会出现编译错误ngc。这也是针对提前编译的特定答案。

于 2016-08-17T14:55:53.617 回答
86

编辑:这个答案现在不正确。我发布时没有关于该主题的官方指导,但正如@Yaroslov(优秀且正确)的回答中所解释的那样,情况不再如此:Codelizer 现在警告并且 AoT 编译将在组件模板中引用私有变量时失败. 也就是说,在概念层面上,这里的一切都仍然有效,所以我会留下这个答案,因为它似乎很有帮助。


是的,这是意料之中的。

请记住,private其他访问修饰符是 Typescript 构造,而 Component/controller/template 是 Typescript 一无所知的角度构造。访问修饰符控制类之间的可见性:创建一个字段private可以防止其他类访问它,但模板和控制器是存在类中的东西。

这在技术上并不正确,但是(代替理解类与装饰器及其元数据的关系),以这种方式思考它可能会有所帮助,因为重要的事情(恕我直言)是从将模板和控制器分开思考转变实体将它们视为组件构造的统一部分 - 这是 ng2 心智模型的主要方面之一。

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

于 2016-01-03T08:37:52.380 回答
16

即使代码示例表明问题是关于 TypeScript 的,它也没有标签。Angular2 也可用于 Dart,这是与 Dart 的显着区别。

Dart中,模板不能引用组件类的私有变量,因为与 TypeScript 相比,Dart 有效地阻止了来自外部的私有成员的访问。

我仍然支持@drewmoores 的建议,将组件和模板作为一个单元来考虑。

更新(TS) 似乎在 Angular2 TS 以及https://github.com/angular/angular/issues/11422中,对私有属性的离线编译访问将变得更加有限

于 2016-04-13T09:17:05.567 回答
5

解决方法可能是在 ts 文件中使用私有变量并使用 getter。

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

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

于 2018-03-23T19:14:19.950 回答
3

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

可以在此处找到有关 typescript 中类的公共/私有成员的更详细说明:https ://www.typescriptlang.org/docs/handbook/classes.html 。

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

于 2017-03-23T07:54:33.623 回答
1

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

于 2019-04-02T17:29:09.960 回答
0

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

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

}

于 2020-07-23T08:49:07.047 回答
0

我知道这有点晚了,但是即使从 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编译器的描述。它在编译时告诉编译器哪些是可以从模板访问的私有属性,然后在运行时消失。

于 2022-01-18T10:52:10.297 回答