简体   繁体   English

Angular2 - 应该在模板中访问私有变量吗?

[英]Angular2 - should private variables be accessible in the template?

If a variable is declared private on a component class, should I be able to access it in the template of that component?如果变量在组件类上声明为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
}

No, you shouldn't be using private variables in your templates.不,您不应该在模板中使用私有变量。

While I like the drewmoore's answer and see perfect conceptual logic in it, implementationwise it's wrong.虽然我喜欢drawmoore 的答案并在其中看到了完美的概念逻辑,但在实现上它是错误的。 Templates do not exist within component classes, but outside of them.模板不存在于组件类中,而是存在于组件类之外。 Take a look at this repo for the proof.看看这个 repo的证明。

The only reason why it works is because TypeScript's private keyword doesn't really make member private.它起作用的唯一原因是因为 TypeScript 的private关键字并没有真正将成员设为私有。 Just-in-Time compilation happens in a browser at runtime and JS doesn't have any concept of private members (yet?).即时编译发生在运行时的浏览器中,并且 JS 没有任何私有成员的概念(还没有?)。 Credit goes to Sander Elias for putting me on the right track.感谢Sander Elias让我走上正轨。

With ngc and Ahead-of-Time compilation, you'll get errors if you try accessing private members of the component from template.使用ngc和 Ahead-of-Time 编译,如果您尝试从模板访问组件的私有成员,则会出现错误。 Clone demonstration repo, change MyComponent members' visibility to private and you will get compilation errors, when running ngc .克隆演示仓库,将MyComponent成员的可见性更改为私有,运行ngc时会出现编译错误。 Here is also answer specific for Ahead-of-Time compilation.这里也是针对 Ahead-of-Time 编译的特定答案

Edit: This answer is now incorrect.编辑:这个答案现在不正确。 There was no official guidance on the topic when I posted it, but as explained in @Yaroslov's (excellent, and correct) answer, this is no longer the case: Codelizer now warns and AoT compilation will fail on references to private variables in component templates.我发布该主题时没有关于该主题的官方指导,但正如@Yaroslov 的(优秀且正确的)答案中所述,情况不再如此:Codelizer 现在发出警告,并且 AoT 编译将在引用组件模板中的私有变量时失败. That said, on a conceptual level everything here remains valid, so I'll leave this answer up as it seems to have been helpful.也就是说,在概念层面上,这里的一切都仍然有效,所以我会留下这个答案,因为它似乎有帮助。


Yes, this is expected.是的,这是意料之中的。

Keep in mind that private and other access modifiers are Typescript constructs, whereas Component/controller/template are angular constructs that Typescript knows nothing about.请记住, private和其他访问修饰符是 Typescript 构造,而 Component/controller/template 是 Typescript 一无所知的角度构造。 Access modifiers control visibility between classes: Making a field private prevents other classes from having access to it, but templates and controllers are things that exist within classes.访问修饰符控制类之间的可见:将字段设为private可以防止其他类访问它,但模板和控制器是存在类中的东西。

That's not technically true, but (in lieu of understanding how classes relate to decorators and their metadata), it might be helpful to think of it this way, because the important thing (IMHO) is to shift from thinking about template and controller as separate entities into thinking of them as unified parts of the Component construct - this is one of the major aspects of the ng2 mental model.这在技术上不是真的,但是(代替理解类与装饰器及其元数据的关系),以这种方式思考它可能会有所帮助,因为重要的事情(恕我直言)是将模板和控制器分开考虑实体将它们视为组件构造的统一部分——这是 ng2 心智模型的主要方面之一。

Thinking about it that way, obviously we expect private variables on a component class to be visible in its template, for the same reason we expect them to be visible in the private methods on that class.以这种方式思考,显然我们希望组件类上的private变量在其模板中可见,出于同样的原因,我们希望它们在该类的private方法中可见。

Even though the code example indicates the question is about TypeScript it doesn't have the tag.尽管代码示例表明问题是关于 TypeScript 的,但它没有标签。 Angular2 is also available for Dart and this is a notable difference to Dart. Angular2 也可用于 Dart,这是与 Dart 的显着区别。

In Dart the template can't reference private variables of the component class, because Dart in contrast to TypeScript effectively prevents access of private members from outside.Dart 中模板不能引用组件类的私有变量,因为与 TypeScript 相比,Dart 有效地阻止了从外部访问私有成员。

I still back @drewmoores suggestion to think about component and it's template as one unit though.我仍然支持@drewmoores 的建议,即考虑将组件和它的模板作为一个单元。

Update (TS) It seems with offline compilation access to private properties will become more limited in Angular2 TS as well https://github.com/angular/angular/issues/11422更新(TS)似乎在 Angular2 TS 中对私有属性的离线编译访问也会变得更加受限https://github.com/angular/angular/issues/11422

Private variables can be using within the template of component.私有变量可以在组件模板中使用。 See angular2 cheat-sheet for guide: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-child-setter有关指南,请参阅 angular2 备忘单: https ://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-child-setter

A more detailed explanation on public/private members of classes in typescript can be found here: https://www.typescriptlang.org/docs/handbook/classes.html .可以在此处找到有关 typescript 中类的公共/私有成员的更详细说明: https : //www.typescriptlang.org/docs/handbook/classes.html

All members by default are Public.默认情况下,所有成员都是公共成员。 Public members can be accessed from outside the component class along with the class-instance.公共成员可以与类实例一起从组件类外部访问。 But Private members can be accessed only within the class member functions.但是私有成员只能在类成员函数中访问。

A workaround could be using private variables in ts file and using getters.解决方法可能是在 ts 文件中使用私有变量并使用 getter。

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

This is a good approach because the ts file and the html remains independent.这是一个很好的方法,因为 ts 文件和 html 保持独立。 Even if you change the _userName variable name in ts file, you dont have to make any change in the template file.即使您更改了 ts 文件中的 _userName 变量名称,您也不必在模板文件中进行任何更改。

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

In tsconfig.app.json if you provide the 'fullTemplateTypeCheck' option in compiler options you can see all the invalid references in html files of your project at the time of project build.在 tsconfig.app.json 中,如果您在编译器选项中提供“fullTemplateTypeCheck”选项,您可以在项目构建时看到项目的 html 文件中的所有无效引用。

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

} }

I know that this is a little late, but I've been preocuppied with this problem even since Angular2 and finally I've come up with a nice workaround to allow me to have nice proper components API's and also to be able to access private fields in them from templates with proper type checking:我知道这有点晚了,但是即使从 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>

In this way, as you can see, we will have even type checking and all we need in the html template and also a proper API of the component.通过这种方式,如您所见,我们甚至可以在 html 模板中进行类型检查以及我们需要的所有内容以及组件的适当 API。 If in another component we reference the MyComponent class like this:如果在另一个组件中我们像这样引用MyComponent类:

export class OtherComponent {
    private _m: MyComponent;

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

we will notice the property _label is not visible.我们会注意到属性_label是不可见的。

Of course, notice that the class MyComponent should not implement the interface MyComponentPrivateProperties .当然,请注意MyComponent类不应实现接口MyComponentPrivateProperties There will be no implementation for this interface.此接口将没有实现。 This is just a description for the angular ngc compiler.这只是对ngc编译器的描述。 It tells the compiler at compile time which are the private properties that should be accessible from the templates and then dissapears at run time.它在编译时告诉编译器哪些是可以从模板访问的私有属性,然后在运行时消失。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM