网上的三方教程大部分是 AngularJS, 但我要用的是 Angular, 是 AngularJS 的新版本, 有些东西不太一样. 关键这两者名字太像了, 这框架命名竟然不用版本号命名, 而只是比老版本少了两个字符, 搜索起来太坑了......
学习使用时使用的环境: - Node.js: 12.10.0 - npm: 6.10.3 - Angular CLI: 8.3.4
以及 Angular 一些包的环境:
1 | Package Version |
官方文档: 中文文档.
安装与指令
安装
先安装 Node.js.
然后使用 npm
安装 Angular 的命令行界面工具 Angular CLI.
Angular CLI 是一个命令行界面工具, 可用于初始化、开发、构建和维护 Angular 应用. Angular CLI 的主版本会跟随它所支持的 Angular 主版本, 不过其小版本可能会独立发布.
1 | npm install -g @angular/cli |
指令
新建一个项目并运行:
1
2
3
4
5
6
7
8
9
10
11
12# 创建项目文件夹, 生成一些配置文件
# 会有一些个性化配置选择, 比如选择 CSS 还是 LESS,
# JavaScript 还是 TypesCript 等. 选默认的即可.
ng new <project_name>
# 进入项目文件夹
cd <project_name>
# 运行项目
# 新项目自带一个 hello world 程序
# 在 http://localhost:4200/ 访问
ng serve在项目中新建模块:
1
2
3
4
5
6
7
8
9
10
11# 新建一个 Component
# 会在 `src/app` 下创建一个同名文件夹, 默认产生四个文件:
# <name>.component.css, <name>.component.html,
# <name>.component.ts, <name>.component.spec.ts
ng generate component <name>
ng g c <name> # 上面指令的缩写
# 新建一个 Service
# 会在 `src/app` 下创建两个文件 (不产生文件夹):
# <name>.service.ts 和 <name>.service.spec.ts
ng generate service <name>能够
ng generate
的东西还有很多, 但我还没用过.其中
.spec.ts
是单元测试编写用例用的.单元测试
1
2# 在 http://localhost:9876/ 访问
ng test
语法用法
内容太多了, 稍微整理点...
.html
中的语法
这玩意太坑了, 好好的 html 格式各种被魔改, 报错也没处说理去, 很多语法写在了引号内, vscode 插件也没法报语法错误.
关键这些语法也花里胡哨的, 没个规律.
插值语法 (双花括号)
1 | {{ }} |
会把双大括号内的值作为文本渲染出来. 例如
1 | <span id="{{'aaa'}}">{{'233'+666}}</span> |
会被渲染为
1 | <span id='aaa'>233666</span> |
. 同时渲染会执行转义, 例如
1 | <span>{{'<br />'}}</span> |
会被渲染为
1 | <span><br /></span> |
, 而不是
1 | <span><br /></span> |
, 所以想插入标签是不可能的. 它这么做目的是防止恶意注入等问题, 不过也可以使用 ng-bind-html-unsafe 指令来关掉默认的 html标签转义 (没用过, 用到了再写).
插值可以使用变量, 变量可以是 .ts
中定义的全局变量或函数, 也可以是 .html
中父标签定义的局部变量. 例如:
1 | <ng-container *ngFor="let item of this.items"> |
*ngIf
, *ngFor
写在 HTML 标签中.
例如在 Component 的 .ts
中定义了全局变量:
1 | export class ItemComponent implements OnInit { |
, 则在 Component 的 .html
中:
1 | <div *ngFor="let item of this.items; let i = index;"> |
会被渲染为:
1 | <div><span>aa</span></div> |
可以看到, 对于 ngIf
, 条件成立则渲染该标签 (及其子标签), 否则不渲染.
对于 ngFor
, 可以看到渲染是包括 for 语句所在的标签的, 即重复渲染的是当前标签, 而不是仅仅重复子标签.
两者注意事项
*ngIf
, *ngFor
不能同时存在于一个标签. 如
1 | <div *ngIf="..." *ngFor="..."></div> |
是非法的, 可以用 ng-container 拆开, 改写为
1 | <ng-container *ngIf="..."> |
*ngIf
注意事项
我还以为它支持 js/ts 的所有语法, 结果它好像是自己实现了部分语法 (或者支持的语法版本老旧).
我想使用 *ngIf="key in obj"
来判断元素是否在 Object 内, 但它并不能识别, 报错了.
只能使用 *ngIf="obj.hasOwnProperty(key)"
来判断.
同时它也不支持 async
异步语法. *ngIf="func1(); func2();"
没问题, *ngIf="func1(); async func3();"
会报错. 只能想别的办法.
*ngFor
注意事项
如果我们希望重复多个同级标签, 却又不想用一个多余的标签包裹它们 , 要用 ng-container.
1
2
3
4
5<ng-container *ngFor="let item of this.items">
<div>ooooo</div>
<div>{{item}}</div>
<div>xxxxx</div>
</ng-container>被渲染为:
1
2
3
4<div>ooooo</div><div>aa</div><div>xxxxx</div>
<div>ooooo</div><div>bb</div><div>xxxxx</div>
<div>ooooo</div><div>cc</div><div>xxxxx</div>
<div>ooooo</div><div>dd</div><div>xxxxx</div>引号内末尾的封号可加可不加.
*ngFor="let e of arr"
与*ngFor="let e of arr;"
, 以及*ngFor="let e of arr; let i = index"
与*ngFor="let e of arr; let i = index;"
都可以, 只要中间的封号加了就行.遍历的不同语法:
遍历 Array:
let e of arr
.遍历 Array 同时需要知道元素的数组下标:
let e of arr; let i = index
.遍历 Object (字典):
let e of obj | keyvalue
. 调用方法:,
.
<ng-container></ng-container>
不会在最终编译出来的网页中存在该标签, 作用是框住一些元素, 方便 ngFor 和 ngIf 针对内部的元素进行操作. 或者配合 ng-template
使用 ( 见 ng-template
部分).
1 | <div> |
会被渲染为
1 | <div> |
, 相当于直接去掉了这个壳.
<ng-template></ng-template>
不会在最终编译出来的网页中存在该元素及其子元素, 这只是定义了一个模板. 只有在被 ng-container
调用时显现在调用的位置.
例子:
1 | <!-- 定义模板, 模板 id 为 displaySetting, 传入参数 nodeData, 定义模板内变量 item 并赋值为 nodeData. --> |
骚操作: 使用 ng-template 和 ng-container DFS 一颗树并输出:
(以下代码从真实代码提取的, 但是改完没跑一下测试, 应该能跑通...吧)
1 | let tree = { |
1 | <ng-template #dfs let-item='data'> |
输入输出语法 ()
, []
, [()]
懒得写了, 官方教程这一块写的还算清晰.
.ts
语法
ng generate
指令生成时已经写好了基础模板.
但是我发现 Service 无法 implements OnInit, 实现了这个接口也不会初始化.
constructor()
与 ngOnInit()
区别
ngOnInit 是 Angular Component 的生命周期中的一环, 一般尽量使用 ngOnInit. constructor 是类的初始化, 比 ngOnInit 更早, 可能会出现获取遍历的值为 undefined.
踩坑
ng serve
报错
报错如下:
1 | 系统找不到指定的路径。 |
是依赖包没正确安装.
在项目目录下, 先删除 node_modules
文件夹, 然后运行 npm install
(或 yarn
, 如果 npm install
不成功的话) 以安装 package.json
内的库.
国内源加速
其实这算 Node.js 的问题. 淘宝的源:
1 | npm install -g cnpm --registry=https://registry.npm.taobao.org |