angular自学笔记

Angular

一、初步上手

1.1、介绍

Angualr是谷歌开发的一款开源的web前端框架,诞生于2009年,由Misko Hevery 等人创建,后为Google所收购。是一款优秀的前端JS框架,已经被用于Google 的多款产品当中。

根据项目数统计angular (1.x 、2.x 、 4.x、5.x、6.x、7.x 、8.x、9.x)是现在网上使用量最大的框架。

Angular基于TypeScript,和react、vue相比 Angular更适合中大型企业级项目

目前2019年12月25日angular最新版本 angular9.x。根据官方介绍,Angular每过几个月就会更新一个版本。Angular2.x以后所有的Angular版本用法都是一样的,此教程同样适用于Angular7.x 、 Angular8.x、Angular9.x以及未来的其它版本…

注意:学习Angular需TypeScript基础

1.2、安装Angular Cli

  • 运行环境:NodeJS
  • 安装Angular Cli
    • npm install -g @angular/cli
    • 使用ng v,查看版本

注意:angular Cli对node版本要求比较严格,注意警告提示的node版本

1.3、创建、运行项目

  • 创建项目

    • ng new 项目名:如ng new testObj

      • Would you like to add Angular routing?	//是否安装angular路由
        Mhich stylesheet fornat would you like to use?//选择何种css处理器
        css
        scss
        sAss
        LESS
        Stglus
        
  • 安装依赖

    • 进入项目目录,执行npm i
  • 运行项目

    • 执行ng serve --open

IE8不支持angular项目

1.4、目录结构

app				//放置组件和根模块的文件夹
assets			//静态资源文件夹
environments 	//环境相关文件夹
.browserslistrc	//浏览器配置支持文件
favicon.ico		//网页图标
index.html		//入口文件
karma.conf.js	//端对端测试文件
main.js			//项目入口文件
polyfill.js		//项目填充库
styles.css		//公共样式文件,文件类型由创建项目时决定
test.ts			//测试入口文件
package.json	//npm配置文件

二、基础

2.1、创建组件

终端执行ng g查看可新建文件类型

ng g 类型名称 指定目录

#例子:创建新组件至app下方components中的news文件夹
ng g component components/news

组件路径视乎默认app文件夹为根目录

  • 使用命令创建的组件,会自动创建对应的CSS,HTML,ts文件
  • 且会在app.module.ts中自动引入并配置

2.2、组件数据绑定

  • 在组件ts文件中定义数据
import { Component, OnInit } from '@angular/core';

@Component({
  selector: '...',			//使用这个组件的名称
  templateUrl: '...',		//这个组件的html
  styleUrls: ['...']		//这个组件的css
})
//语法参照typescript中的类
export class NewsComponent implements OnInit {
  public newsTitle = "每日新闻"		//
  msg:string = '今日气温较高'		   //不加属性修饰符typescript会默认属性为public
    							   //定义数据是应指定数据类型(typescript规范
    
    
  constructor() { }		//构造函数

  ngOnInit(): void {
  }

}
  • 在html中使用数据

<h2>我是新闻组件h2>
<ul>
  <li>{{newsTitle}}li>
ul>


2.3、绑定属性值



鼠标hover,演示属性动态绑定

2.4、解析html代码




2.5、属性遍历


  • {{item}}

    index:{{i}}

    是否为奇数:{{odd}}

    是否为偶数:{{even}}

    是否为第一个:{{f}}

    是否为最后一个:{{l}}

2.6、图标引入









  // 不用写相对图片目录,默认从assets文件夹查找
  public imgSrc ='assets/image/icon-yellow_05.png'

2.7、条件渲染

  • gnIf
    • 类似v-if

为true的时候我显示

为true的时候我显示

为false的时候我显示

  • ngSwitch

<span [ngSwitch]="stateNum">
<p *ngSwitchCase=1>
1表示失败
p>
<p *ngSwitchCase=2>
 2表示成功
p>
<p *ngSwitchDefault>
  默认情况
p>
span>

2.8、绑定属性和样式

  • ngClass


我演示ngClass
  • ngStyle




我在演示ngStyle

2.9、事件绑定



点我! {{str}}

ts文件

...
export class HeaderComponent implements OnInit {
  ...

  public str = 'FBI open door!!!'

  ...
  constructor() { }

  ngOnInit(): void {
  }
  // 自定义方法
  run(e:any):void{
    alert('跑呀!!!')
    // 改变数据
    this.str = 'FBI incoming !!!'
    console.log(e)
  }
  // 参数必须指定类型
  inputFn(e:any):void{
    console.log(e)
  }
}

2.10、双向绑定

  • 注意需在app.module.ts引入FormsModule
...

// FormsModule实现双向绑定
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [   //配置当前项目运行的组件
    ...
  ],
  imports: [        //配置当前模块运行依赖的其他模块
    ....
    FormsModule
  ],
   ...
})
    ...
  • 使用双向绑定


{{bdstr}}

三、管道

管道(pipe),作用和用法类似Vue中的过滤器(filter)

3.1、angular官方常用管道

  • 大小写转换

{{'Str' | uppercase}}

//转换成大写

{{'Str' | lowercase}}

//转换成小写
  • 大小写转换

{{new Date().getTime() | date:'yyyy-MM-dd HH:mm:ss' }}

3.2、自定义管道

使用ng g pipe 放置目录/管道名创建

例如:在app下的pipe下创建mydemo管道

ng g pipe pipe/mydemo

下面为管道ts文件内容

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  // 定义引用管道名
  name: 'mydemo'
})
export class MydemoPipe implements PipeTransform {
  // transform(value: unknown, ...args: unknown[]): unknown {
  //   return null;
  // }
  // 自定义管道函数(函数名固定为transform)
  transform(value: string): string {
    if(!value) return value;
    if(typeof value !== 'string') {
      throw new Error('Invalid pipe argument for WelcomePipe');
    }
    return "Welcome to " + value;
  }
}

app.module.ts中引入管道

// 引入管道
import { MydemoPipe } from './pipe/mydemo.pipe';
//配置管道
@NgModule({
  declarations: [   //配置当前项目运行的组件
    MydemoPipe
  ],
)}

使用自定义管道


{{ '天津' | mydemo }}

四、双向绑定表单练习

  • toDoList
  • 搜索

五、服务

存放公共方法或属性,可创建多个服务,服务之间可相互调用

5.1、创建服务

ng g service 指定目录/服务名称

5.2、引入服务

感觉类似Vue中的VueX?

  1. app.module.ts

    // 引入服务
    //MyserviceService为myservice.service中暴露出的类名
    import { MyserviceService } from './services/myservice.service'
    
    @NgModule({
      declarations: [   //配置当前项目运行的组件
        ...
      ],
      imports: [        //配置当前模块运行依赖的其他模块
        ...
      ],
      providers: [  MyserviceService ],    //配置项目所需要的服务
      ...
    })
    
  2. 在组件中

    // 引入该组件需使用的服务
    import { MyserviceService } from '../../services/myservice.service'
    
    export class TodolistComponent implements OnInit {
      ...
    
      // 初始化服务
      // 依赖注入???
      //public 自定义变量名:引入的服务名
      constructor(public myserve:MyserviceService) { 
        
      }
      ngOnInit(): void {
        // 使用服务中的方法
        this.myserve.show()
      }
    }
    

5.3、持久化

通过sessionStorage或localStorage实现

六、ViewChild

类似Vue中的ref ?

6.1、获取dom节点

//在组件ts中引入ViewChild
import { Component, OnInit,ViewChild,... } from '@angular/core';

//在html中使用	#自定义名称	标识dom节点
/*
我是ViewChild绑定的div
*/ //使用ViewChild修饰器获取dom节点 export class ViewchildComponent implements OnInit { //@ViewChild('dom上使用 # 绑定的名称') 自定义变量名:any @ViewChild('mybox') aaa:any constructor() { } ngOnInit(): void { } ngAfterViewInit(): void { console.log(this.aaa,'打印mybox') } }

6.2、获取子组件

//绑定子组件app-news
/*
	
	
*/


//使用子组件方法
export class ViewchildComponent implements OnInit {
//通过ViewChild获取子组件
  @ViewChild('news') news:any
  constructor() { }

  ngOnInit(): void {
  
  }

  ngAfterViewInit(): void {
      //查看子组件信息
    console.log(this.news,'打印news')
    // 调用子组件方法
    this.news.say()
  }
}

七、组件

7.1、父子组件

7.2、组件通信

7.2.1、父组件给子组件传值

@input类似Vue中的 props

父组件不仅可以给子组件传递数据,还可以把自己的方法以及整个父组件传递给子组件

  • 父组件中


<app-search [msg]="message" [fn]='run' [fcpn]='this'>app-search>
  • 子组件中
// 子组件中引入Input模块
import { Component, OnInit,Input } from '@angular/core';
export class SearchComponent implements OnInit {
	...

  // 使用Input修饰器绑定数据
  @Input() msg:any
  @Input() fn:any
  @Input() fcpn:any
  constructor() { }

  ngOnInit(): void {
    console.log(this.msg,'父组件传递的数据')
    // 执行父组件方法
    this.fn()
    // console.log('执行父组件方法')
    // 输出父组件
    console.log(this.fcpn,'输出父组件')
  }
  
}
7.2.2、子组件给父组件传值

有以下两种方法:

  • 使用ViewChild获取子组件
  • 使用@Output触发父组件的方法,类似Vue中的$emit
//在子组件中引入	Output,EventEmitter	模块
import { Component, OnInit,Input ,Output,EventEmitter} from '@angular/core';

export class SearchComponent implements OnInit {
...

  //通过Output修饰器声明变量,接收 实例化EventEmitter
  @Output() private myouter = new EventEmitter

  constructor() { }
...
  // 给父组件传值
  doting(){
    // 广播数据
    console.log(111)
    this.myouter.emit('我是子组件传递给父组件的数据')
  }
}


<app-search (myouter)="getChild($event)">app-search>



八、生命周期

  • ngOnChanges - 当数据绑定输入属性的值发生变化时调用
  • ngOnInit - 在第一次 ngOnChanges 后调用 //组件和指令初始化完成,并不是真正的dom加载完成
  • ngDoCheck - 自定义的方法,用于检测和处理值的改变
  • ngAfterContentInit - 在组件内容初始化之后调用
  • ngAfterContentChecked - 组件每次检查内容时调用
  • ngAfterViewInit - 组件相应的视图初始化之后调用 //建议此处操作dom
  • ngAfterViewChecked - 组件每次检查视图时调用
  • ngOnDestroy - 指令销毁前调用
函数名 描述
constructor 构造函数中除了使用简单的值对局部变量进行初始化之外,什么都不应该做。(它不是生命周期函数
ngOnChanges 当Angular(重新)设置数据绑定输入属性时响应。该方法接受当前和上一属性值的SimpleChange对象。 当被绑定的输入属性值发生改变时调用,首次调用一定会发生在ngOnInit之前
ngOnInit 在Angular第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件。 在第一轮ngOnChanges ()完成之后调用,只调用一次 。======使用ngOnInit 的两个原因:1、在构造函数之后马上执行复杂的初始化逻辑;2、在Angular设置完输入属性之后,对该组件进行准备。
ngDoCheck 检查,在ngOnInit 执行。可以在该生命周期中对数据进行检查操作
ngAfterContentInit 组件渲染之后的周期函数,当把内容投影进组件之后调用,第一次ngDoCheck 后调用,只调用一次
ngAfterContentChecked 检查,和ngDoCheck 类似
ngAfterViewInit 视图加载完成后调用。第一次ngAfterContentChecked ()之后调用,只调用一次
ngAfterViewChecked 检查,和ngDoCheck 类似
ngOnDestroy 组件销毁前调用
// implements后面为生命函数对应的规范,可以不引入
// 若引入则需按照其规范书写
// 引入多个时使用 , 分割
export class LifefnComponent implements OnInit {
  public msg:string = ''
  constructor() { 
    console.log('00---我是constructor构造函数')
  }
  ngOnChanges(): void {
    console.log('01---我是 ngOnChanges 生命周期函数')
  }
  ngOnInit(): void {
    console.log('02---我是 ngOnInit 生命周期函数')
  }
  ngDoCheck(): void {
    console.log('03---我是 ngDoCheck 生命周期函数')
  }
  ngAfterContentInit(): void {
    console.log('04---我是 ngAfterContentInit 生命周期函数')
  }
  ngAfterContentChecked(): void {
    console.log('05---我是 ngAfterContentChecked 生命周期函数')
  }
  ngAfterViewInit(): void {
    console.log('06---我是 ngAfterViewInit 生命周期函数')
  }
  ngAfterViewChecked(): void {
    console.log('07---我是 ngAfterViewChecked 生命周期函数')
  }
  ngOnDestroy(): void {
    console.log('08---我是 ngOnDestroy 生命周期函数')
  }
}

九、RxJS

9.1、介绍

RxJS是 Reactivex编程理念的JavaScript版本。ReactiveX来自微软,它是一种针对异步数据流的编程。简单来说,它将一切数据,包括HTTP请求,DOM事件或者普通数据等包装成流的形式,然后用强大丰富的操作符对流进行处理,使你能以同步编程的方式处理异步数据,并组合不同的操作符来轻松优雅的实现你所需要的功能。

RxJS是一种针对异步数据流编程工具,或者叫响应式扩展编程;可不管如何解释RxJS其目标就是异步编程,Angular引入 RxJS为了就是让异步可控、更简单。

通俗理解:RxJS主要用于异步编程,和Promise相似,但功能更加强大。

RxJS是一个第三方模块,但Angular自身已经集成了RxJS,就是为了让异步可控、更简单。

目前常见的异步编程方法

  • 回调函数
  • 事件监听/发布订阅
  • Promise
  • RxJS

9.2、Promise和RxJS处理异步对比

使用方法类似

但RxJS中可以中途撤回、Rxjs可以发射多个值、Rxjs提供了多种工具函数等等。

// 在使用的文件中使用RxJS
// 引入RxJS的Observable
import { observable, Observable } from 'rxjs';

#定义函数
...
  // Promise
  getPromiseData(){
    return new Promise((resolve,reject) => {
      setTimeout(() => {
        let data = {
          name:'张三',
          age:16
        }
        resolve(data)
      }, 2000);
    })
  }

  // RxJS
  getRxjsData(){
    return new Observable((observer) =>{
      setTimeout(() => {
        let data = {
          name:'张三',
          age:16
        }
        observer.next(data)     //成功调用.next方法
        // observer.error('出错啦')  //失败调用.error方法
      }, 2000);
    })
  }

#调用
    //3. promise获取异步数据
    this.myserve.getPromiseData().then((res) => {
      console.log(res,'Promise')
    })

    // 4.RxJS获取异步数据
    this.myserve.getRxjsData().subscribe((res) => {
      console.log(res,'RxJS')
    })

9.3、unsubscribe取消订阅

Promise创建之后,动作是无法撤回的.Observable不一样,动作可以通过unsubscribe方法中途撤回

    // 5.使用unsubscribe撤回操作
    // 如果异步方法还未执行,就可以撤回
    let rxjsFn = this.myserve.getRxjsData()
    let data2 = rxjsFn.subscribe((res) => {
      console.log(data,'RxJS的subscribe值')
    })
    // 通过subscribe的值来取消
    // 效果:一秒后取消getRxjsData的执行
    setTimeout(() => {
      // unsubscribe取消订阅
      data2.unsubscribe()
    }, 1000);//此处的延迟时间小于getRxjsData中的延迟(模拟在异步函数执行前撤回

9.4、订阅多次执行

#serve中定义
  // 多次执行对比
  // Promise
  getPromiseDataInterval(){
    return new Promise((resolve,reject) => {
      setInterval(() => {
        let data = {
          name:'张三',
          age:16
        }
        resolve(data)
      },1000)
    })
  }
  // RxJS
  getRxjsDataInterval(){
    return new Observable((observe) => {
      setInterval(() =>{
        let data = {
          name:'张三',
          age:16
        }
        observe.next(data)
      },1000)
    })
  }
#引用
    // 6.Promise多次执行(Promise不能做到
    let p2 = this.myserve.getPromiseDataInterval()
    p2.then((res) => {
      console.log(res,'Promise多次执行')
    })
    // 7.RxJS多次执行
    let r2 = this.myserve.getRxjsDataInterval()
    r2.subscribe((res) => {
      console.log(res,'RxJS多次执行')
    })

9.5、Angular6.x之前使用RxJS的工具函数

**注意:**Angular6之后的RxJS版本为6.x,如果想在Angular6.x之前的方法使用RxJS6.x版本中的某些方法,必须安装rxjs-compat模块才可以使用map、filter

angular6后官方使用的是RxJS6 的新特性,所以官方给出了一个可以暂时延缓我们不需要修改rsjx代码的办法。

  • 安装
    • npm install rxjs-compat

9.6、Angular6.x之后RxJS6.x的变化以及使用

Angular6.x之后使用则不需要安装rxjs-compat

RxJS6改变了包的结构,主要变化在import方法和operator上面,以及使用pipe()

  • 引入模块

    • //在使用的组件中引入模块
      // 引入RxJS的map,filter工具模块
      import { map,filter } from 'rxjs/operators'
      
  • 使用

    •     // 8.通过工具方法对数据进行处理
          let num = this.myserve.getRxjsNumInterval()
          // 在管道pipe中使用工具方法
          // filter返回满足条件的值
          // num.pipe(
          //   filter((item:any) =>{
          //     return item%2 == 0
          //   })
          // ).subscribe((res) => {
          //   console.log(res,'-----filter')
          // })
      
          // map为变量,与ES5中类似
          // num.pipe(
          //   map((item:any) => {
          //     return item * item
          //   })
          // ).subscribe((res) => {
          //   console.log(res,'-----map')
          // })
      
      
          // 可在管道(pipe)中使用多个方法
          num.pipe(
            filter((item:any) => {
              return item%2 ==0
            }),
            map((item) => {
              return item * item
            })
          ).subscribe((res) => {
            console.log(res,'-----多个工具结合使用')
          })
      

9.7、RxJS延迟执行

通过throttleTime实现

//引入
import { throttleTime } from 'rxjs/operators'

//使用
let rxjsFn = this.myserve.getRxjsData()
rxjsFn.pipe(
	throttleTime(1000)
).subscribe((res) => {
    console.log(res)
})

十、数据交互

10.1、Angular自带模块HttpClientModule

Angular5.x以后的get、post和服务器交互使用的是HttpClientModule模块

  • 引入

    • //在app.moudle.ts中引入HttpClientModule模块,并进行配置
      // 引入HttpClientMidule模块,实现数据交互
      import { HttpClientModule } from '@angular/common/http'
      ...
      @NgModule({
        declarations: [   //配置当前项目运行的组件
          ....],
        imports: [        //配置当前模块运行依赖的其他模块
         ...
          HttpClientModule
        ],
        ...
      })
      ...
      
  • 组件中导入

    • //  在组件中引入HttpClient模块,可以借为HttpClientModule模块的一个服务
      import { HttpClient } from '@angular/common/http';
      
  • 声明服务并使用方法

    • export class NetworkComponent implements OnInit {
      
        // 声明服务
        constructor(private myhttp:HttpClient) { }
        // get方法
        getData(){
          let url = 'http://a.itying.com/api/productlist'
          //HttpClicent返回的是一个RxJS对象。使用subscribe进行调用
          this.myhttp.get(url).subscribe((res) => {
            console.log(res)
          })
        }
          
        // post提交数据
        postData(){
          // 手动定义请求头
          const myHttpOptions = {
            headers :new HttpHeaders({'Content-Type':'application/json'})
          }
          this.myhttp.post('http://47.104.7.144:3001/api/adminlogin',
            {"name":'ICPFAadmin',"pwd":'admin'},
            // myHttpOptions
            ).subscribe((res) => {
              console.log(res)
          })
        }
      }
      

10.2、第三方axios

  • 安装

    • npm install axios --save
  • 引入

    • 推荐在服务文件中引入

    • // 引入axios
      import axios from 'axios';
      export class AxiosService {
        axiosGetData(){
          // 返回axios,在外部调用.then方法
         return axios({
            url:'http://47.104.7.144:3001/api/adminlogin',
            method:'post',
            data:{
              name:'ICPFAadmin',
              pwd:'admin'
            }
          })
        }
      }
      
  • 使用

    • // 在需要的组件中引入服务
      import { AxiosService } from 'src/app/services/axios.service';
      ...
      export class AxiosComponent implements OnInit {
      // 声明服务
        constructor(private myaxios:AxiosService) { }
        
        ngOnInit(): void {
        // 使用服务中的axios
          this.myaxios.axiosGetData().then((res) => {
            console.log(res,'axios')
          })
        }
      
      }
      

十一、路由

  • 在创建项目时选择安装路由即可新建一个包含路由的项目

  • 若创建项目时没有安装路由,则可在app目录下新建app-routing.module.ts路由配置文件

    • // 路由配置模块
      import { NgModule } from '@angular/core';
      import { RouterModule, Routes } from '@angular/router';
      
      const routes: Routes = [];
      
      @NgModule({
        imports: [RouterModule.forRoot(routes)],
        exports: [RouterModule]
      })
      export class AppRoutingModule { }
      
  • 并在app.module.ts引入并配置

    • //引入路由配置文件
      import { AppRoutingModule } from './app-routing.module';
      ...
      @NgModule({
        declarations: [ ... ],
        imports: [        //配置当前模块运行依赖的其他模块
          AppRoutingModule,
          ...
        ],
        providers: [ ... ],    //配置项目所需要的服务
        bootstrap: [AppComponent]   
      })
      
  • app.component.html中增加

    • 
      
      

11.1、配置路由

  • 在路由文件中引入对应的组件

    • // 路由配置模块
      import { NgModule } from '@angular/core';
      import { RouterModule, Routes } from '@angular/router';
      
      // 引入路由需要的组件
      import { NewsComponent } from './components/news/news.component';
      import { TodolistComponent } from './components/todolist/todolist.component';
      
      // 配置路由
      const routes: Routes = [
        {
          // 路径
          path:'home',
          // 对应的组件
          component:TodolistComponent
        },
        {
          path:'news',
          component:NewsComponent
        },
        // 重定向方法一
        // {
        //   path:'',
        //   // 重定向
        //   redirectTo:'home',
        //   pathMatch:'full'
        // }
        // 重定向方法二
        {
          path:'**',
          // 重定向
          redirectTo:'news',
        }
      ];
      
      
      
      
      @NgModule({
        imports: [RouterModule.forRoot(routes)],
        exports: [RouterModule]
      })
      export class AppRoutingModule { }
      

11.2、路由传参

  • 配置路由

    •   // 动态路由传值
        {
          path:'router/:routedata',
          component:RouterComponent
        },
        // get传参
        // {
        //   path:'router',
        //   component:RouterComponent
        // },
      
  • 传递




<a [routerLink]="[ '/router', '我是数据' ]">路由传值---paramsa>

<a [routerLink]="[ '/router']" [queryParams]="{myid:1,name:'张三'}">路由传值---queryParamsa>
  • 获取

    • 在组件中引入ActivatedRoute

    • // 引入ActivatedRoute模块
      import { ActivatedRoute } from '@angular/router';
      
      ...
      
      export class RouterComponent implements OnInit {
          
      // 声明ActivatedRoute
        constructor(public myactiveroute:ActivatedRoute) { }
        ngOnInit(): void {
          console.log(this.myactiveroute,'当前激活路由')
          //返回值是一个RxJS对象,需使用 subscribe 调用
          //方法一
          this.myactiveroute.params.subscribe((res) =>  {
            console.log(res,'路由参数---params')
          })
            
          //方法二
          this.myactiveroute.queryParams.subscribe((res) =>  {
            console.log(res,'路由参数---queryParams')
          })
        }
      
      }
      

11.3、事件跳转

  • 动态路由和普通路由跳转
// 引入Router
import { Router } from '@angular/router';
...
export class RoutermainComponent implements OnInit {
// 声明
  constructor(public myrouter:Router) { }

  ngOnInit(): void {
  }
  goPage(){
    // 动态路由
    this.myrouter.navigate(['/router','我是动态路由的数据'])
  }
  goHome(){
    // 普通路由
    this.myrouter.navigate(['/home'])
  }
}
  • get路由跳转
// 引入Router
// 事件跳转get路由还需引入NavigationExtras
import { Router,NavigationExtras } from '@angular/router';

export class RoutermainComponent implements OnInit {
// 声明
  constructor(public myrouter:Router) { }

  ...
  goGet(){
    // Get路由
    // 定义传递的数据,并将类型指定为NavigationExtras
    let myqureyData:NavigationExtras = {
      queryParams:{
        name:'哇哈哈',
        age:12
      }
    }
    this.myrouter.navigate(['/routerget'],myqureyData)
  }
}

11.4、嵌套路由

//配置路由
  {
    path:'routermain',
    component:RoutermainComponent,
    children:[
      {
        path:'child',
        component:RouterchildComponent
      }
    ]
  },

前往子路由


你可能感兴趣的:(学习笔记,node.js,angular)