@@ -236,7 +236,7 @@ tag: Angular
236236- 在模板视图中使用管道
237237- 可以使用CLI命令行`ng g pipe 管道名`<br>
238238<div align="center" >
239- <img src=.. /images/Common_pipe.png width="350" height="350"/>
239+ <img src=" /images/Common_pipe.png" width="350" height="350"/>
240240</div>
241241
242242` ` ` typescript
@@ -386,14 +386,14 @@ tag: Angular
386386|Axios|也是XHR,只是进一步的封装而已|比原生简单;基于Promise处理响应;可以排队、并发|
387387|NGHttpClient|也是XHR,只是进一步的封装而已|比原生要简单;基于“观察者模式(23种设计模式之一)”处理响应;可以排队、并发、撤销|
388388|Fetch|不再是XHR,是W3C提出的新技术,有望取代XHR|比XHR从根本上更加先进;天然基于Promise|
389- |||
390389
391390### Angular官方提供的服务对象——HttpClient
392391- HttpClient服务:是Angular提供的用于发起异步XHR请求的对象
393392- 使用步骤:
394393 - 1,在主模块中导入HttpClientModule模块
395394 - 2,在组件中声明依赖于HttpClient服务对象,就会被自动注入
396395 - 3,调用HttpClient实例实现异步请求` this.http.get(url).subscribe((res) => {} )`
396+
397397 ` ` ` typescript
398398 //component.ts页面内容
399399 export class bookcomponent {
@@ -429,14 +429,214 @@ tag: Angular
429429 </table>
430430 <button (click)="loadMore()">加载下一页数据</button>
431431 ` ` `
432+
432433 - 4,组件的生命周期钩子函数
433434 - Angular中的组件的声明周期钩子函数调用顺序:
434435 - constructor():组件对象被创建先调用构造函数
435436 - ngOnChanges():组件绑定的属性值发生改变
436437 - <b>ngOnInit()</b>:组件初始化完毕-等同于Vue.js的mounted
437- - ngDoCheck():开发者自定义变更检测。
438- - ngAfterContentInit():在组件内容初始化后调用。
439- - ngAfterContentChecked():在组件内容每次检查后调用。
438+ - ngDoCheck():开发者自定义变更检测
439+ - ngAfterContentInit():在组件内容初始化后调用
440+ - ngAfterContentChecked():在组件内容每次检查后调用
440441 - ngAfterViewInit():在组件视图初始化后调用。
441- - ngAfterViewChecked():在组件视图每次检查后调用。
442- - ngOnDestroy():在指令销毁前调用。
442+ - ngAfterViewChecked():在组件视图每次检查后调用
443+ - ngOnDestroy():在指令销毁前调用,组件即将被从DOM树上卸载,适合执行一些资源释放性语句,例如:定时器销毁...
444+
445+ - 5,父子组件传递--重点&难点
446+
447+ ` ` ` typescript
448+ //创建父组件
449+ export class parentComponent {
450+ userName:string='user'
451+ doCry(e:string){//接收子组件传递的数据
452+ //e为子组件传递过来的数据
453+ this.userName=e
454+ }
455+
456+ //输出父组件内部的识别符的子组件,c0为html中的标识符
457+ @ViewChild('c0',{static:ture})
458+ private child;
459+ print(){
460+ console.log(this.child)
461+ }
462+
463+ }
464+
465+ //创建子组件(更改内容组件)
466+ export class childModifyComponent{
467+ //子=>父,子组件通过触发事件(其中携带者数据),把数据传递给父组件提供事件处理方法
468+ userInput:string = null
469+
470+ //事件发射器
471+ @Output() //输出型属性,可以向父组件传递数据
472+ cryEvent = new EventEmitter()
473+
474+ doModify(){//button (click)绑定事件
475+ //子组将要将数据传递给父组件
476+ //console.log(this.userInput)
477+ this.cryEvent.emit(this.userInput)
478+ }
479+ }
480+
481+ //创建子组件(图片组件)
482+ export class childPhotoComponent {
483+ //普通属性不能被父组件传值
484+ //private childName:string = null
485+
486+ @Input()//父=>子
487+ //输入型属性父组件可以利用这种属性传值,一个装饰器只能装饰一个,多个参数需要多个装饰器
488+ childName:string = null
489+ }
490+
491+ ` ` `
492+ ` ` ` typescript
493+ //parent.html内容中引用事件和参数
494+ <div style="background-color: brown;width: 1000px;height: 1000px;" #c0>
495+ //#XX标识符
496+ <h2>{{userName}}的博客</h2>
497+
498+ //监听子组件的事件
499+ <app-child-modify (cryEvent) = "doCry($event)" #c1></app-child-modify>
500+ <app-child-photo [childName]="userName"></app-child-photo>
501+ </div>
502+ ` ` `
503+
504+ # ## 路由和导航
505+ - 多页面应用:一个项目中有多个完整HTML文件,使用超链接跳转--销毁一棵DOM树,同步请求另一棵,得到之后再重建新的DOM树;不足:DOM树妖反复重建,间隔中客户端一片空白
506+ - 单页面应用:称为SPA(Single Page Application),整个项目中有且只有一个“完整的”HTML文件,其他的“页面”都只是DIV片段;需要哪个“页面”就将其异步请求下来,“插入”到“完整的”HTML文件中。单页应用的优势:整个项目中客户端只需要下载一个HTML页面,创建一个完整的DOM树;页面跳转都是一个DIV替换另一个DIV而已--能够实现过程动画。缺点:不利于SEO访问优化
507+ - Angular中使用“单页应用”的步骤
508+ - 定义“路由词典”——[{URL-组件},{URL-组件},...]
509+ - 为每个路由组件分配一个路由地址
510+ - 注册“路由词典”
511+ - 创建路由组件挂载点——称为“路由出口”
512+ - 访问测试
513+ - 注意:
514+ - 路由词典中的路由地址不能以/开头或结尾,但中间可以包含/
515+ - 路由词典中可以指定一个默认首页地址:`{path:'',component:...}`
516+ - 路由词典中的每个路由要么指定component(由哪个组件提供内容),要么指定redirect(重定向到另一个路由地址)
517+ - 路由词典中可以指定一个匹配任意地址‘**’,注意该地址用于整个路由词典的最后一个
518+ - 路由跳转/导航:从一个路由地址跳转到另一个;实现方案:
519+ - 方法一:使用模板跳转方法<br>
520+ ` <any routerLink="/ucenter">` ;注意:用于任意标签上,跳转地址应该以/开头,防止以相对方式跳转
521+ ` ` ` typescript
522+ //在app.module.ts文件中声明路由词典--路由地址和路由组件的对应集合
523+ let routes=[
524+ {path:'index',component:IndexComponent},
525+ {path:'plist',component:ProductListComponent},
526+ {path:'pdetail',component:ProductDetailComponent},
527+ {path:'ucenter',component:UserCenterComponent},
528+ //重定向需要指定“路由地址匹配方式”为“full”或“profix”
529+ {path:'',redirectTo:'pdetail',pathMatch:'full'}
530+ //任意地址,如404网页;**地址匹配任意地址,任意地址不能放在最上面,有顺序的查找
531+ {path:'**',vomponent:NotFoundComponent}
532+ ]
533+
534+ @NgModule({
535+ imports:[RouterModule.forRoot(routes)] //导入路由模块,并注册路由词典,用于根模块中
536+ })
537+
538+ //在.html文件中创建路由挂载点
539+ //访问测试通过浏览器打开,如 http://127.0.0.1:4200/index | http://127.0.0.1:4200/ucenter
540+ <router-outlet> </router-outlet>
541+
542+ //传统的超链接可以跳转,但属于DOM树完全重建
543+ <a href="ucenter">进入用户中心</a>
544+
545+ //routerLink可以用在任何标签上的,如按钮、属性等
546+ <a routerLink="/ucenter">进入用户中心</a>
547+
548+ //路由嵌套修改路由词典:
549+ //注意:“用户中心”下的二级路由组件挂载点/路由出口应该放在UserCenter.component.html中
550+ {path:'user/center',
551+ component:IndexComponent,
552+ children:[//嵌套二级路由
553+ {path:'info',component:XXXComponent},
554+ {path:'security',component:XXXComponent},
555+ ]},
556+
557+ ` ` `
558+ - 方式二:使用脚本方法
559+ - 注意:Router类是RouterModule提供的一个服务类,声明依赖即可使用
560+ ` ` ` typescript
561+ //在.html文件中
562+ <button (click)="jump()">跳转页面</button>
563+
564+ //在class中依赖注入
565+ export class ParentModule(){
566+ constructor(private router:Router){}
567+
568+ jump(){//跳转到用户中心--需要“路由器”服务
569+ this.router.navigateByUrl('/ucenter')
570+ }
571+ }
572+ ` ` `
573+ - Vue.js中的路由跳转的机制有哪些?
574+ 1.hash法:只需要修改url中的hash部分:http://127.0.0.1/index.html#/ucenter<br>
575+ 2.history法:需要修改window.history对象,从而支持浏览器自带的后退按钮:http://127.0.0.1/ucenter;(Angular只有这种方法)
576+ - 路由参数:
577+ - 在路由词典定义路由地址时,其中可以包含可变的参数 :
578+ - 在.html文件中,为路由参数提供具体的参数值
579+ - 到目标路由组件,可以读取“当前路由地址”中的参数
580+
581+ ` ` ` typescript
582+ //app.module.ts文件
583+ let routers = [ //':'lid表示参数名
584+ {path='producdetail/:lid',component:ProductDetailComponent},
585+ ]
586+
587+ //在.html文件中,为路由参数提供具体的参数值
588+ <a routerLink="/producdetail/5">进入5</a>
589+ <a routerLink="/producdetail/13">进入13</a>
590+ <a routerLink="/producdetail/21">进入21</a>
591+
592+ //在producu.component.ts文件中
593+ export class ProductDetailComponent implements Oninit{
594+ private productId:number
595+
596+ //声明依赖:读取参数需要“当前的路由”服务对象
597+ constructor(private route:ActivatedRoute){}
598+
599+ ngOnInit(){
600+ //组件初始化完成,读取路由参数,进而根据此参数查询
601+ this.route.params.subscribe((data)=>{
602+ console.log('得到订阅的路由参数:')
603+ console.log(data)
604+ this.productId = data.lid
605+ })
606+ }
607+ }
608+ ` ` `
609+
610+ - 路由守卫:
611+ - Angular提供了“路由守卫(Guard)”来实现访问路由组件前的检查功能:如果检查通过(return true)就放行,如果不通过(return false)不放行
612+ - ` ng g guard GuardName`
613+ ` ` ` typescript
614+ //创建Login.guard.ts文件
615+ @Injectable({ //路由守卫是“可注入”服务对象
616+ providedIn:'root'
617+ })
618+ export class LoginGuard implements CanActivate {
619+ //依赖注入路由
620+ constructor(private router:Router){}
621+
622+ private isLogin = false //此处应该根据用户是否登入而改变
623+ canActivate(){
624+ if(this.isLogin){//可以激活后续的组件
625+ return true
626+ }else{//阻止激活后续的组件
627+ this.router.navigateByUrl('/index')
628+ return false
629+ }
630+ }
631+ }
632+
633+ //在app.module.ts文件中
634+ {path:'user/center',
635+ component:IndexComponent,
636+ //路由守护
637+ canActivate:[LoginGuard],
638+ children:[//嵌套二级路由
639+ {path:'info',component:XXXComponent},
640+ {path:'security',component:XXXComponent},
641+ ]},
642+ ` ` `
0 commit comments