Angular:常见问题集锦

一、提供商注册到模块中还是组件中?

1.通常,优先把模块中具体特性的提供商注册到模块中(@NgModule.providers),而不是组件中(@Component.providers)。

应该把全应用级提供商添加到根模块AppModule中,而不是还是根组件AppComponent

这是因为惰性加载模块及其组件可以注入AppModule中的服务,却不能注入AppComponent中的。

只有当该服务必须对AppComponent组件树之外的组件不可见时,才应该把服务注册进AppComponentproviders中。 这是一个非常罕见的异常用法。

2.当你必须

把服务实例的范围限制到某个组件及其子组件树时,就把提供商注册到该组件中

 指令的提供商也同样照此处理。


二、不要在共享模块中把应用级单例添加到providers中:

虽然很多组件都共享着同一个服务例,但它们是靠 Angular 的依赖注入体系实现的,而不是模块体系。

比如很多组件都注入了UserService, 在整个应用程序中,只应该有一个UserService的实例,并且它只应该有一个提供商。换句话说,UserService是全应用级单例, 我们不希望每个模块都各自有它的实例。 而如果由SharedModule提供UserService,就会导致铁板钉钉的危险, 否则如果一个惰性加载模块导入了此共享模块,就会导致它自己也生成一份此服务的实例。


三、我要如何知道一个模块或服务是否已经加载过了?

某些模块及其服务只能被根模块AppModule加载一次。 在惰性加载模块中再次导入这个模块会导致错误的行为,这个错误可能非常难于检测和诊断。为了防范这种风险,我们可以写一个构造函数,它会尝试从应用的根注入器中注入该模块或服务。如果这种注入成功了,那就说明这个类是被第二次加载的,我们就可以抛出一个错误,或者采取其它挽救措施。

constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
  if (parentModule) {
    throw new Error(
      'CoreModule is already loaded. Import it in the AppModule only');
  }
}

四、模板引用变量 ( #var )

模板引用变量通常用来引用模板中的某个DOM元素,它还可以引用Angular组件或指令或Web Component,模板引用变量的作用范围是整个模板。不要在同一个模板中多次定义同一个变量名,否则它在运行期间的值是无法确定的。

使用井号 (#) 来声明引用变量(我们也可以用ref-前缀代替#):

#phone的意思就是声明一个名叫phone的变量来引用<input>元素。

扫描二维码关注公众号,回复: 5909633 查看本文章
<input #phone placeholder="phone number">

我们可以在模板中的任何地方引用模板引用变量,比如在<input>上的phone变量就是在模板另一侧的<button>上使用的:

<input #phone placeholder="phone number">
    <!-- lots of other elements -->
    <!-- phone是输入元素,将它的value值传递给事件处理程序 -->
<button (click)="callPhone(phone.value)"> Call </button>

大多数情况下,Angular会把模板引用变量的值设置为声明它的那个元素。 在上一个例子中,phone引用的是表示电话号码的<input>框。 "拨号"按钮的点击事件处理器把这个input值传给了组件的callPhone方法。

不过,指令也可以修改这种行为,让这个值引用到别处,比如它自身。 NgForm指令就是这么做的:

<form (ngSubmit)="onSubmit(heroForm)" #heroForm="ngForm">
  <div class="form-group">
    <label for="name">Name
      <input class="form-control" name="name" required [(ngModel)]="hero.name">
        <!-- name属性的用途是有效性验证和对表单元素的变更进行追踪 -->
    </label>
  </div>
 <button type="submit" [disabled]="!heroForm.form.valid">Submit</button>
</form>
<div [hidden]="!heroForm.form.valid">{{submitMessage}}<div>

这里的heroForm实际上是一个Angular NgForm 指令的引用, 因此具备了跟踪表单中的每个控件的值和有效性的能力。

应用实例:

<div class="container">
  <div [hidden]="submitted">
    <h1>Hero Form</h1>
      <!-- 模版引用:heroForm是一个Angular NgForm 指令的引用 -->
    <form (ngSubmit)="onSubmit()" #heroForm="ngForm">
      <div class="form-group">
        <label for="name">Name</label>
       <!-- 模版引用 -->
        <input type="text" class="form-control" id="name" required
               [(ngModel)]="model.name" name="name" #name="ngModel">
        <div [hidden]="name.valid || name.pristine"
             class="alert alert-danger">
          Name is required
        </div>
      </div>

      <div class="form-group">
        <label for="alterEgo">Alter Ego</label>
        <input type="text" class="form-control" id="alterEgo"
               [(ngModel)]="model.alterEgo" name="alterEgo">
      </div>

      <div class="form-group">
        <label for="power">Hero Power</label>
       <!-- 模版引用 -->
        <select class="form-control" id="power" required
           [(ngModel)]="model.power" name="power" #power="ngModel">
          <option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>
        </select>
        <div [hidden]="power.valid || power.pristine" class="alert alert-danger">
          Power is required
        </div>
      </div>

      <button type="submit" class="btn btn-success" 
         [disabled]="!heroForm.form.valid">Submit</button>
      <button type="button" class="btn btn-default" (click)="newHero(); 
         heroForm.reset()">New Hero</button>
    </form>
  </div>

<!-- 表单提交之后显示 -->
  <div [hidden]="!submitted">
    <h2>You submitted the following:</h2>
    <div class="row">
      <div class="col-xs-3">Name</div>
      <div class="col-xs-9  pull-left">{{ model.name }}</div>
    </div>
    <div class="row">
      <div class="col-xs-3">Alter Ego</div>
      <div class="col-xs-9 pull-left">{{ model.alterEgo }}</div>
    </div>
    <div class="row">
      <div class="col-xs-3">Power</div>
      <div class="col-xs-9 pull-left">{{ model.power }}</div>
    </div>
    <br>
     <!-- 点击Edit按钮之后,可编辑的表单不再隐藏,可以重新编辑提交 -->
    <button class="btn btn-primary" (click)="submitted=false">Edit</button>
  </div>
</div>

五、为什么建议每个文件只放一个类?

在同一个文件中有多个类容易造成混淆,最好避免。 开发人员期望每个文件只放一个类。如果我们蔑视这个建议,并且 —— 比如说 —— 把HeroServiceHeroesComponent组合在同一个文件里, 就得把组件定义放在最后面! 如果把组件定义在了服务的前面, 在运行时抛出空指针错误。

猜你喜欢

转载自blog.csdn.net/qq_36451496/article/details/86550482