Angular开发常见问题

本文是作者对Angular开发常见问题的介绍,包括Angular开发常见问题的优势、实现细节、相关资料等,这些步骤可以帮助作者提高Angular开发常见问题的效率。

10月 26, 2017 · 4 分钟阅读时长 · 1823 字 · -阅读 -评论 · 编程开发

Angular开发总会遇到诸多的问题,这里我将自己在开发中遇到的主要问题总结一番,方便自己偶尔翻查,也兴许能够帮大家解决些问题。

说明:*本文持续更新*,所贴代码由于篇幅限制,有些只是部分,建议直接去GitHub-ISSUE中去看

目录

  1. [innerHTML]中的JavaScript不能执行吗?
  2. 同时订阅路由参数和查询参数即params和queryParams
  3. 多异步请求并行处理
  4. *ngFor遍历对象属性
  5. 组件类的继承性
  6. 如何使组件样式超出组件作用域
  7. 下拉列表选项布尔类型转换
  8. 模板标签
  9. CLI下index.html页面未模板化,如何动态更改内容
  10. CLI下如何添加第三方CSS
  11. httpclient下的拦截器使用

[innerHTML]中的JavaScript不能执行吗?

答案:YES,不行的,这个牵扯到Angular的安全机制,官方介绍看这里 Angular官方的意思是倘若支持了这个,便存在攻击性,本身就是很可怕的,试想,Angular本身就是个JS框架,倘若支持了html代码块可执行JS,本身就会打破这个框架,带来致命的安全问题。

另外对于HTML,想让NG支持解析,需要注入DomSanitizer服务,将HTML标记位可信任。如果web中常用,建议做成管道,例子看这里

另外使用bypassSecurityTrustHtml,经测试,情况如下

  • 页内CSS正常
  • 外链CSS正常
  • 执行JS不可以
  • 嵌入媒体正常

如果我们还是希望能够执行HTML代码块中的JS,其实就需要换个角度去解决,比如iframe?对吧,总是有办法的。

同时订阅路由参数和查询参数即params和queryParams

进入一个视图页面时候,我们经常需要订阅参数,参数是有很多类型的,路径参数、查询参数,锚点参。我们如果利用嵌套形式写的话,会是这样子:

    this.route.queryParams.subscribe(qparams => {
            alert(qparams['title']);
            this.route.params.subscribe(params => {
                alert(params['id']);
            });
        })

但是这样子的代码是极难维护的,其实RXJS有对应的解决办法,可以这样子实现

 let obsCombined = Observable.combineLatest(this.route.params, this.route.queryParams, (params, qparams) => ({
            params,
            qparams
        }));
        obsCombined.subscribe(ap => {
            console.log(ap);
            let params = ap['params'];
            let qparams = ap['qparams'];
            alert(qparams['title']);
            alert(params['id']);
        });

这样子减少了嵌套,代码直接清爽不少。

注意一个细节:import {Observable} from "rxjs/Rx"; 写成import {Observable} from "rxjs/Observable";会报错误Property 'combineLatest' does not exist on type 'typeof Observable'.

*ngFor遍历对象属性

有时需要遍历对象属性,但是Angular的ngFor指令是只支持遍历数组的,所以需要转换对象,这个时候可以考虑封装个管道,代码如下


import {Pipe, PipeTransform} from "@angular/core";
/**
 * 对象返回数组
 */
@Pipe({
  name: 'keys'
})
export class KeysPipe implements PipeTransform {

  transform(value: any, args?: any): any {
    return Object.keys(value);
  }
}

实际上,就是用了JS的Object.keys()方法,该方法作用如下

The Object.keys() method returns an array of a given object’s own enumerable properties, in the same order as that provided by a for…in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).

管道做好后,使用方法如下:

<div *ngFor="let key of facetFields|keys">
key:{{key}},
value:{{facetFields[key]}}
      </div>

多异步请求并行处理

有时需要多请求结果同时进行处理,嵌套去做的话,会是如此

this.http.get('/api/test1')
      .subscribe(res1 => {
        this.http.get('/api/test2').subscribe(res2 => {
          this.res1 = res1;
          this.res2 = res2;
        });
      });

这种结构臃肿,难以维护,使用Rxjs的forkJoin操作符

const req1 = this.http.get('/api/test1');
const req2 =this.http.get('/api/test2');

Rx.Observable.forkJoin(req1, req2).subscribe(
res => {
 this.res1 = res[0];
 this.res2 = res[1];
)) 

只有当多请求结果都得到时,才会通知我们

组件类的继承性

ng-v2.3版本加入了对于组件继承性的支持,这样进一步的提升代码的复用性。

组件继承性说明:

  • meta注解,比如@input,@output
  • 构造函数
  • 组件生命周期

以上三者均支持复用,官方说明看这里,链接

image

如何使组件样式超出组件作用域

如何使得A组件的样式在A的子组件比如B中能够使用的

除了将样式写外链CSS即全局CSS之外,其实还可以修改视图封装模式即view encapsulation mode达到组件样式可以出去,使得其他组件可以使用。只需要配置比如A组件的视图模式,如下配置

@Component({
    selector: 'app-css',
    templateUrl: './css.component.html',
    styleUrls: ['./css.component.css'],
    encapsulation: ViewEncapsulation.None
})

如上,则该组件下的各级组件dom元素均可使用该样式。

注意

组件继承不支持模板和样式,任何操作dom的行为都应该物理分离。

实际Demo看这里

下拉列表选项布尔类型转换

当我们对下拉列表进行ngModel双向绑定,如果我们的对象是非字符串类型,比如boolean,当用户选择选项后,会变成字符串。

如果下拉选项被提供了非字符串类型,缺省value是会进行字符串类型转换,如果使用ngValue,就可以保持类型不变。

<select [(ngModel)]="isList" (ngModelChange)="viewTypeChanged()">
    <option [ngValue]="true">列表浏览</option>
    <option [ngValue]="false">分组浏览</option>
</select>

模板标签

ng-template我们经常搭配ngIf指令等使用,如下:

<div *ngIf="isList;else elseBlock">
    <ul>
        <li *ngFor="let item of items">
            <a routerLink='../detail/{{item.id}}' [queryParams]="{title:item.title}">
   
Alan H
Authors
开发者,数码产品爱好者,喜欢折腾,喜欢分享,喜欢开源