zoukankan      html  css  js  c++  java
  • angular9的学习(四)

    指令 Directive

    inputs

    跟上一节一样,不过需要自己试试才知道

    <div appEnabled [aaa]="123"  [bbb]="456">12313131</div>
    
    @Directive({
      selector: '[appEnabled]',
      inputs:['aaa']
    })
    export class EnabledDirective implements OnInit{
      public aaa;
      @Input('bbb') b;
      constructor() {
      }
      ngOnInit(){
        console.log(this.aaa);
        console.log(this.b);
      }
    }
    

    outputs

    父
    <div appEnabled (bankName)="add($event)" (child)="add($event)>12313131</div>
    
    add(e){
        console.log(e)
    }
    子
    @Directive({
      selector: '[appEnabled]',
      outputs:['bankName']
    })
    export class EnabledDirective implements OnInit{
      public bankName=new EventEmitter();
      @Output('child') c = new EventEmitter();
      constructor() {
      }
      ngOnInit(){
        this.bankName.emit('gggg');
        this.c.emit('ccc')
      }
    
    }
    
    

    providers 令牌

    这个跟之前保持一致

    exportAs 别名

    我思考的时候一直在想这个有什么作用,后面才发现了,这个跟查找子组件的想法一样

    @Directive({
      selector: '[appEnabled]',
      exportAs: 'enabledDir'
    })
    
    父
    <div appEnabled #dir='enabledDir'>12313131</div>
    export class EnabledComponent implements OnInit ,AfterViewInit{
      constructor() {
      }
      @ViewChild('dir') dir;
      ngAfterViewInit(){
        console.log(this.dir);
      }
    }
    

    queries

    思考半天,还是不清楚这个属性的用意

    host

    绑定特定的键值对属性到DOM上

    @Directive({
      host:{
        'one':'two'
      }
    })
    

    HostListener 监听DOM事件

    eventName 要监听的DOM事件。
    args 事件发生时传递给处理程序方法的一组参数。
    <div appEnabled>点我</div>
    
    @Directive({
      selector: '[appEnabled]',
    })
    
    export class EnabledDirective{
      @HostListener('click',['$event.target']) clickHandler(val){
        console.log(val);
      }
    
    }
    监控全局键盘事件
     @HostListener('window:keydown', ['$event'])
      keydownN(v:KeyboardEvent) {
        console.log(v);
      }
    

    [属性绑定]

    可以绑定一些自定义属性

    <div [attr.name]="113">wqwwqwqwq</div>
    

    [class绑定]

    <h1 [class.aaa]="isSpecial">12112</h1>
     isSpecial=true;
    

    [style绑定]

    <h1 [style.color]="'red'">122112</h1>
    <h1 [style.font-size.px]="20">122112</h1>
    <div [ngStyle]="{'font-size.px': 20, color: 'white', background: 'red'}">
      Text in this div is 20px size, white color on red background.
    </div>
    

    伪事件

    <input (keyup.enter)="enterHandler()">
    <input (keydown.esc)="escHandler()">
    <input (keyup.shift.f)="shiftFHandler()">
        
    按 enter
    按 esc
    按 shift+f
    

    main.ts

    可以放入全局功能的js

    动态组件

    简单版

    需求:添加一个动态组件,然后3s后删掉
    模块
    
    @NgModule({
      declarations: [BlockComponent, UserComponent, EnabledComponent, RefsComponent, EnabledDirective, DyOneComponent, DyTwoComponent,AdHostDirective],
      imports: [
        BlockRoutingModule,
        ComomModule
      ],
      providers: [BlockService],
      entryComponents: [DyOneComponent, DyTwoComponent] //添加动态的组件
    })
    
    指令
    import {Directive, ViewContainerRef} from '@angular/core';
    
    @Directive({
      selector: '[appAdHost]'
    })
    export class AdHostDirective {
    
      constructor(public viewContainerRef:ViewContainerRef) { }
    }
    
    页面
    <ng-template appAdHost></ng-template>
    
    ts
    
    export class BlockComponent implements OnInit, AfterViewInit {
      @ViewChild(AdHostDirective) dlHost: AdHostDirective;
    
      constructor(private cfr: ComponentFactoryResolver) {
      }
    
      ngAfterViewInit() {
        this.dlHost.viewContainerRef.createComponent(
          this.cfr.resolveComponentFactory(DyTwoComponent)
        );
        setTimeout(() => {
          this.dlHost.viewContainerRef.clear();
        }, 3000)
      }
    
      ngOnInit(): void {
      }
    
    }
    

    稍微复杂点的版本

    写一个定时器,3s切来切去

    export class BlockComponent implements OnInit, AfterViewInit, OnDestroy {
      @ViewChild(AdHostDirective) dlHost: AdHostDirective;
      num: number = 0;
      interval: any;
      comArr = [DyOneComponent, DyTwoComponent];
    
      constructor(private cfr: ComponentFactoryResolver) {
      }
    
      ngAfterViewInit() {
        this.addComponent()
      }
    
      ngOnDestroy() {
        clearInterval(this.interval)
      }
    
      addComponent() {
        this.interval = setInterval(() => {
          this.num = this.num > 1 ? 0 : this.num;
          this.dlHost.viewContainerRef.clear();
          this.dlHost.viewContainerRef.createComponent(
            this.cfr.resolveComponentFactory(this.comArr[this.num])
          );
          this.num++;
        }, 3000)
      }
    
      ngOnInit(): void {
    
      }
    
    }
    

    路由 Router

    const appRoutes: Routes = [
      { path: 'crisis-center', component: CrisisListComponent },
      { path: 'hero/:id',      component: HeroDetailComponent },
      {
        path: 'heroes',
        component: HeroListComponent,
        data: { title: 'Heroes List' }
      },
      { path: '',
        redirectTo: '/heroes',
        pathMatch: 'full'
      },
      { path: '**', component: PageNotFoundComponent }
    ];
    

    路由器出口

    <router-outlet></router-outlet>
    

    多视口

    <router-outlet></router-outlet>
    <router-outlet name='left'></router-outlet>
    <router-outlet name='right'></router-outlet>
    
      {
        path: '',
        component: DyTwoComponent,
        outlet:'left'
      },
      {
        path: '',
        component: RefsComponent,
        outlet:'right'
      }
    

    弄了半天才踩出这个坑, 注意了name属性确定了, 该插件不能动态设置,只能写静态的,我尝试了很多种方法,跳转都报错,应该是静态的吧

    路由导航

    <a routerLinkActive="aaa" *ngFor="let item of arr" [routerLink]="item" [routerLinkActiveOptions]="{exact:true}">点我</a>
    
    public arr=['','/pro/1','/one','/two'];
    

    在链接的路由变成活动的时候将css添加类

    <a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
    <a routerLink="/user/bob" [routerLinkActive]="['class1', 'class2']">Bob</a>
    

    [routerLinkActiveOptions]="{exact:true}" 仅仅当url与链接完全匹配时,才添加routerLinkActive里面的类

    可以把RouterLinkActive 实例分配给模板变量,检查isActive 状态

    简单的说就是鼠标点击的时候,拿到这个状态

    <a routerLink="/user/bob" routerLinkActive="aaa" #rla="routerLinkActive">
      Bob {{ rla.isActive ? '是' : '否'}}
    </a>
    
    <a routerLink="/user/bob">link to user component</a>
    
    动态的
    [routerLink]=['/team', teamId, 'user', userName, {details: true}] 
    /team/11/user/bob;details=true
    

    如果第一段是前置/,./,../

    /		根目录
    ./		当前路由的子级
    ../		上升一个级别
    

    关于# ?

    <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" fragment="education">
      link to user component
    </a>
    
    /user/bob#education?debug=true
    

    ActivatedRoute 从节点中提取信息

    export class EnabledComponent implements OnInit {
    
      constructor(private route: ActivatedRoute) {
      }
    
    
      ngOnInit(): void {
    
        this.route.params.subscribe(val=>{
          console.log(val); //动态的参数
        });
        this.route.url.subscribe(val=>{
          console.log(val); // url
        });
        this.route.queryParamMap.subscribe(val=>{
          console.log(val); // 所有的映射的参数
        })
        this.route.paramMap.subscribe(val=>{
          console.log(val); //当前的,**这个用的多一些**
        })
      }
    }
    

    监控路由发生变化的事件

    要写的专业点,修改原来的学习(二)的内容

    export class AppComponent implements OnInit{
      routeEnd:Observable<NavigationEnd>;
      constructor(private router: Router) {
        this.routeEnd = this.router.events.pipe(
          filter(evt => evt instanceof NavigationEnd)
        ) as Observable<NavigationEnd>;
      }
      ngOnInit(){
        this.routeEnd.subscribe(val=>{
          console.log(val);
        })
      }
      ngOnDestroy(){
       this.routeEnd.unsubscribe() //不要忘记处理手动订阅
      }
    }
    
    

    路由复用策略

    也可以叫缓存路由

    RouteReuseStrategy

    abstract  class  RouteReuseStrategy {
      // 判断是否复用路由
      abstract  shouldReuseRoute(future:  ActivatedRouteSnapshot, curr:  ActivatedRouteSnapshot): boolean
      // 存储路由快照&组件当前实例对象
      abstract  store(route:  ActivatedRouteSnapshot, handle:  DetachedRouteHandle):  void
      // 判断是否允许还原路由对象及其子对象
      abstract  shouldAttach(route:  ActivatedRouteSnapshot): boolean
      // 获取实例对象,决定是否实例化还是使用缓存
      abstract  retrieve(route:  ActivatedRouteSnapshot):  DetachedRouteHandle  |  null
      // 判断路由是否允许复用
      abstract  shouldDetach(route:  ActivatedRouteSnapshot): boolean
    }
    

    shouldReuseRoute

    当要在路由之间导航的时候调用,调用这个方法并不代表一定会跳转到新的页面。
    如果返回true, 那么不会进行跳转;如果返回false,才会跳转并且执行其余的那几个方法。

    shouldDetach

    离开页面的时候调用的方法, 会比落地页面的构造函数先执行

    如果返回true,则会执行 store方法

    store

    shouldDetach 返回true的时候调用,可以在这里存储被detach下来的RouteHandle,

    shoeldAttach

    判断是否恢复之前的store路由

    如果返回true的话,retrieve 方法会被调用

    retrieve

    返回之前存储的RouteHandle,如果返回null 的话则不起作用

    创建一个服务

    import {Injectable} from '@angular/core';
    import {
      ActivatedRouteSnapshot,
      RouteReuseStrategy,
      DetachedRouteHandle
    } from '@angular/router'
    
    @Injectable()
    export class BlockService implements RouteReuseStrategy{
      public handlers: { [key: string]: DetachedRouteHandle } = {};
    
      //表示对路由允许复用
      shouldDetach(route: ActivatedRouteSnapshot): boolean {
        //默认对所有路由复用 可通过给路由配置项增加data: { keep: true }来进行选择性使用,代码如下
        //如果是懒加载路由需要在生命组件的位置进行配置
        if (!route.data.keep) {
          return false;
        }
        return true;
      }
    
      //当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象
      store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
        this.handlers[route.routeConfig.path] = handle;
      }
    
      //若path在缓存中有的都认为允许还原路由
      shouldAttach(route: ActivatedRouteSnapshot): boolean {
        return !!route.routeConfig && !!this.handlers[route.routeConfig.path];
      }
    
     // 从缓存中获取快照,若无则返回null
      retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
        if (!route.routeConfig) return null;
        if (route.routeConfig.loadChildren) return null; //在loadChildren路径上通过修改自定义RouteReuseStrategy中的检索函数时从不检索分离的路由。
        return this.handlers[route.routeConfig.path];
      }
    
      //进入路由触发,判断是否同一路由
      shouldReuseRoute(future: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean {
        return future.routeConfig === current.routeConfig;
      }
    }
    

    在app.module.ts导入这个服务

     providers: [{
        provide: RouteReuseStrategy,
        useClass: BlockService
      }],
    
  • 相关阅读:
    leetcode 851. Loud and Rich
    674. 最长连续递增序列
    896. 单调数列
    905. 按奇偶排序数组
    917. 仅仅反转字母
    922. 按奇偶排序数组 II
    925. 长按键入
    929. 独特的电子邮件地址
    933. 最近的请求次数
    自己动手丰衣足食写java贪吃蛇
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/12628632.html
Copyright © 2011-2022 走看看