路由
安装路由
单页面应用程序中,我们要使用路由,路由也是一个模块,我们可以直接安装
由于路由是一个特殊的模块,所以安装的时候要添加--routing 参数
在路由中,为了访问组件方便。我们可以将路由配置文件放在根目录下,此时添加 --flat参数
创建路由模块指令
ng g module --routing --flat app
创建时候,提示是否将原来的app-module覆盖,
如果开发过,不要覆盖,选择n
此时跳过对app-module的更新了,因此后面我们还要配置全局模块
如果是新项目,可以覆盖,选择y
使用路由
使用路由分成六步
第一步 在全局模块中,配置路由模块
第二步 定义页面组件
第三步 在路由配置中,引入页面组件
第四步 定义路由规则,类似vue,是一个数组,每一个成员代表一条规则
path 表示路由规则(不要以/开头)
component 定义渲染的组件
name 路由规则名称
第五步 定义路由渲染位置
vue:通过router-view
react:通过Switch
ng6中,通过router-outlet组件定义路由的渲染位置
第六步 配置根路由,
默认创建的是子路由,想变成根路由,要将forChild改成forRoot即可
ng6中,默认是browser路由策略,通过更改path实现的,需要后端的配置
我们常用hash路由策略,只需要为forRoot或者forChild传递第二个配置参数,
userHash: true
默认路由
vue中通过path匹配*定义默认路由
ng6中通过path匹配**定义默认路由
重定向路由
vue中通过redirect属性,配置重定向路由
ng6中通过redirectTo属性,配置重定向路由
注意:默认路由要放在最后面。
举例:
imports: [
BrowserModule,
// 1 引入路由模块
AppRoutingModule
],
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
// 3 引入页面组件
// ts语法,支持解构的时候,为属性起别名
import { HomeComponent as Home } from './pages/home/home.component';
import { ListComponent as List } from './pages/list/list.component';
import { DetailComponent } from './pages/detail/detail.component';
// 4 定义路由规则
const routes: Routes = [
// 首页
{ path: 'home', component: Home },
// 列表页
{ path: 'list/:id', component: List },
// 详情页
{ path: 'detail/:id', component: DetailComponent },
// 输入ickt进入详情页
{ path: 'ickt', redirectTo: 'detail/ickt' },
// 默认路由
{ path: '**', component: Home }
];
@NgModule({
// 更改配置
// 更改路由策略,使用hash策略
imports: [RouterModule.forRoot(routes, { useHash: true })],
exports: [RouterModule]
})
export class AppRoutingModule { }
单元测试
单元测试又叫单测,是为了保证我们的代码指令,避免代码中出现bug的一种测试方式。
ng6内置了单测,通过jestmine工具进行测试
jestmine写描述不支持中文。
进入测试,执行 ng test指令即可
describe
定义整体测试描述的方法
第一个参数表示描述
第二个参数是一个函数,在函数中我们进行测试
it
定义单元测试方法
第一个参数表示测试功能点
第二个参数是函数,在里面我们定义断言方法
expect
定义断言方法
参数就是断言表达式,
方法执行完毕,我们判断结果
断言方法
toBe
类似于`===`
expect(true).toBe(true);
toEqual
比较变量字面量的值
expect({ foo: 'foo'}).toEqual( {foo: 'foo'} );
toMatch
匹配值与正则表达式
expect('foo').toMatch(/foo/);
toBeDefined
检验变量是否定义
var foo = {
bar: 'foo'
};
expect(foo.bar).toBeDefined();
toBeNull
检验变量是否为`null`
var foo = null;
expect(foo).toBeNull();
toBeTruthy
检查变量值是否能转换成布尔型`真`值
expect({}).toBeTruthy();
toBeFalsy
检查变量值是否能转换成布尔型`假`值
expect('').toBeFalsy();
toContain
检查在数组中是否包含某个元素
expect([1,2,4]).toContain(1);
toBeLessThan
检查变量是否小于某个数字
expect(2).toBeLessThan(10);
toBeGreaterThan
检查变量是否大于某个数字或者变量
expect(2).toBeGreaterThan(1);
toBeCloseTo
比较两个数在保留几位小数位之后,是否相等,用于数字的精确比较
expect(3.1).toBeCloseTo(3, 0);
toThrow
检查一个函数是否会throw异常
expect(function(){ return a + 1;}).toThrow(); // true
expect(function(){ return a + 1;}).not.toThrow(); // false
toHaveBeenCalled
检查一个监听函数是否被调用过
toHaveBeenCalledWith
检查监听函数调用时的参数匹配信息
数据双向绑定
在vue中我们通过v-model实现数据双向绑定
ng6也是基于MVVM模式实现的框架,因此也支持数据双向绑定,通过ngModel指令
数据双向绑定有两个方向
数据由模型进入视图
通过数据绑定实现的,因此要使用[]语法糖
数据由视图进入模型
通过事件监听实现的,因此要使用()语法糖
所以在ng6中,使用数据双向绑定,要使用两个语法糖: []
, ()
由于我们要先绑定事件,再绑定数据,因此使用方式
[(ngModel)]=”demo”
绑定的数据一定要在组件中声明
数据双向绑定ngModel指令,属于对表单元素的操作,因此要安装表单模块FormsModule
在全局模块的imports中,引入该模块
一组表单元素可能会有很多字段,一一获取太麻烦了,如果可以提供一个命名空间,就方便多了
因此我们通常将一组表单数据放在一个变量下。
在ts6中,为了获取这组数据的结构,我们要定义模型类来说明
在组件类中,为数据实例化模型类
举例:
<p>
<label for="">用户名</label>
<!-- <input type="text" [(ngModel)]="username"> -->
<input type="text" [(ngModel)]="data.username">
</p>
<p>
<label for="">密码</label>
<!-- <input type="text" [(ngModel)]="password"> -->
<input type="text" [(ngModel)]="data.password">
</p>
<p>
<button (click)="showResult()">展示结果</button>
</p>
周期方法
beforeEach 每个单测执行前,执行的方法
afterEach 每个单测执行后,执行的方法
beforeAll 所有单测执行前,执行的方法
afterAll 所有单测执行后,执行的方法
测试机床
ng6中,为了测试组件,提供测试机床 TestBed
通过该方法,可以模拟创建组件,并注入相关信息
单测思想很好,但是前端主要开发页面,因此对于页面效果,一些用户交互等等,单测是无法测试的,所以工作中,我们也常常用单测测试一些业务逻辑。所以相对来说,单测对于前端来说收益不大。