zoukankan      html  css  js  c++  java
  • angular11源码探索三[深入指令demo篇]

    angular-masterpackagescommonsrcdirectives

    模拟ngClass 方法

    @Directive({
      selector: '[appNkClass]'
    })
    export class NkClassDirective implements DoCheck {
    
      constructor(private renderer: Renderer2,
                  private hostElement: ElementRef
      ) {
      }
    
      @Input('appNkClass') cssMap: Record<string, boolean>;
    
      ngDoCheck(): void {
        for (let [key, value] of Object.entries(this.cssMap)) {
          if (value === true) {
            this.renderer.addClass(this.hostElement.nativeElement, key);
          } else {
            this.renderer.removeClass(this.hostElement.nativeElement, key);
          }
        }
      }
    }
    
    <h1 [ngClass]="{active:flag}">xxxxxxxxxxx</h1>
    <h1 [appNkClass]="{active:flag}">xxxxxxxxxxx</h1>
    

    click属性里面编写方法

    <button (click.long)="clickAdd()">Click2</button>
    
    @Directive({
      selector: '[click.long]'
    })
    export class clickLongDirective implements OnDestroy {
      /*设置一个方法,两s后执行*/
      private clickTimer: any;
      @Output('click.long')
      longClickEvent = new EventEmitter();
    
      @HostListener('mousedown')
      onMouse() {
        clearTimeout(this.clickTimer);
        this.clickTimer = window.setTimeout(() => {
          this.longClickEvent.emit();
        }, 2000);
      }
    
      ngOnDestroy() {
        clearTimeout(this.clickTimer);
      }
    
      constructor() {
      }
    }
    
    

    双向事件绑定

    <input type="text"  [(nkModel)]="names">
    
     @Directive({
      selector: '[nkModel]'
    })
    export class NkModelDirective {
      @Input('nkModel')
      dyName: string = '';
      @Output('nkModelChange')
      emitUpdates = new EventEmitter();
    
      @HostBinding('value')
      get value() {
        return this.dyName;
      }
              //change 事件是失去焦点触发
      @HostListener('input', ['$event'])
      update(event: Event) {
        this.dyName = (event.target as HTMLInputElement).value;
        this.emitUpdates.emit(this.dyName);
      }
    
      constructor() {
      }
    
    }   
    

    断网的时候竟用按钮

    <button (click)="clickAdd()" appNkDisabled>CLIck</button>
    
    @Directive({
      selector: 'button[appNkDisabled]'
    })
    export class NkDisabledDirective {
      /*需求没网的时候禁用按钮*/
      private _offline: boolean = false;
    
      @HostBinding('disabled')
      get isDisabled() {
        return  this._offline
      }
    
      /*断网*/
      @HostListener('window:offline')
      disableButton() {
        this._offline=true;
      }
    
      /*在线*/
      @HostListener('window:online')
      enableButton() {
        this._offline=false;
      }
      constructor() { }
    }
    

    写一个原生的textrea方法

    @Directive({
      selector: 'textarea'
    })
    export class NkDisabledDirective {
      private readonly _textArea: HTMLTextAreaElement;
      @HostBinding('style')
      defaultStyle = {overflow: 'hidden', height: 'auto', resize: 'none'}
    
      // 输入数字的时候,高度随着行数的增加而增加
      @HostListener('input')
      autoExpand() {
        // 主要是随着滚动长度的增加height才会增加
        console.log(this._textArea.scrollHeight);
        //继承父级的高度
        this._textArea.style.height = 'inherit'
        const computed = window.getComputedStyle(this._textArea);
        const height = parseInt(computed.getPropertyValue('border-top-width'), 10) + this._textArea.scrollHeight
          + parseInt(computed.getPropertyValue('padding-bottom'), 10)
          + parseInt(computed.getPropertyValue('border-bottom-width'), 10)
        this._textArea.style.height = height + 'px';
      }
    
      constructor(private hostElement: ElementRef) {
        this._textArea = hostElement.nativeElement
      }
    }
    

    思考一个问题,window用的是全局的

    为了使您的应用程序可以与服务器端渲染一起使用,我建议您不仅使用窗口直通令牌,而且还以SSR友好的方式创建此令牌,而无需完全引用window。Angular具有DOCUMENT用于访问的内置令牌document

    看了写大佬写的

    export const WINDOW=new InjectionToken<Window>(
    'return reference to window',
    {providedIn:'platform',factory:()=>window}
    )
    

    有个, 本地Web API的高质量轻量级包装器

    可以看看源码学习下

    然后把我们写好的WINDOW 注入到页面里面,代替我们写的window

    conststructor(@Inject(WINDOW) private window)
    替换之前的改成 this.window
    

    有时间好好研究依赖注入,服务那块

    *NgIf

    <h1 *nkIf="flag">Hello World</h1>
    
    @Directive({
      selector: '[nkIf]'
    })
    export class NkDisabledDirective {
      @Input('nkIf')
      set IsHidden(shouldHide: boolean) {
        if (shouldHide) {
          this.viewContainer.clear()
        } else {
            // 插入新视图
          this.viewContainer.createEmbeddedView(this.template)
        }
      }
    
      constructor(
        private template: TemplateRef<any>,
        private viewContainer: ViewContainerRef
      ) {
      }
    
    }
    

    ngTemplateOutlet

    将一个或者多个组件插入视图中

    @Directive({
      selector: '[nkComponent]'
    })
    export class NkDisabledDirective {
     /*Type 实例类*/
      @Input('nkComponent')
      set componentToRender(component: Type<any>) {
        // 拿到当前组件dom
        // console.log(this.viewContainer.element);
        // 清空当前的组件
        this.viewContainer.clear()
        // 通过注入器取出 用于获取给定组件类型的工厂函数
        const resolver = this.viewContainer.injector.get(ComponentFactoryResolver);
        // 通过实例化组件
        this.viewContainer.createComponent(resolver.resolveComponentFactory(component))
      }
    
      constructor(
        private viewContainer: ViewContainerRef
      ) {
      }
    
    }
    
    <ng-container *ngTemplateOutlet="bool"></ng-container>
    // 模拟
    <div [nkComponent]="bool"></div>
    
    // 外部引入的组件
      bool = CountDownComponent;
    

    ngFor探索

    @Directive({
      selector: '[nkForMap]'
    })
    export class NkDisabledDirective implements DoCheck {
      @Input('nkForMapIn') map;
      @Input('nkForMapFilter') filter;
      constructor(private viewContainer: ViewContainerRef,
                  private template: TemplateRef<any>) {
      }
    
      ngDoCheck(): void {
        // 可以拿到值
        console.log(this.filter);
        // 进行for-in操作
        Object.keys(this.map).forEach(key => {
          this.viewContainer.createEmbeddedView(this.template,{$implicit:{key:key,value:this.map[key]}})
        })
      }
    }
    
    <ul>
      <li *nkForMap="let entry in user;filter:'s'">{{entry.key}}{{entry.value}}</li>
    </ul>
    
      user = {
        name: 'xxx',
        email: 'bbbb',
        age: 123
      }
    

    获取剪贴栏的内容

    <input type="text" (keydown.paste)="clickDown($event)"  [(ngModel)]="str">
    
      str: string;
     clickDown(content) {
        //获取剪贴栏的内容
        this.str=content
      }
    
    
    @Directive({
      selector: '[keydown.paste]'
    })
    export class NkModelDirective {
      @Output('keydown.paste')
      pasteEvent = new EventEmitter<string>();
    
      @HostListener('keydown', ['$event'])
      async detectPaste(event) {
        // 按下ctrl
        // console.log($event.ctrlKey);
        //     按下p
        // console.log($event.code== 'KeyP');
        // 按下ctrl+i
        // 解析系统剪贴板的文本内容返回一个Promise 。
        // navigator.clipboard.readText()
        if (event.ctrlKey && event.code === 'KeyI') {
          const content = await navigator.clipboard.readText();
          this.pasteEvent.emit(content);
        }
      }
      constructor() {
      }
    }
    

    ngComponentOutlet

    <ng-container *ngComponentOutlet="two"></ng-container>
    
    export class OneComponent implements OnInit, AfterViewInit {
      // 组件
      public two=TwoComponent
    }
    
    <div *ngFor="let comp of comps">
      <ng-container *ngComponentOutlet="comp"></ng-container>
    </div>
    把三个组件放在 comps 数组中
      comps: any[] = [
        OneComponent,
        TwoComponent,
        ThreeComponent
      ];
    
  • 相关阅读:
    Pthread使用总结
    OpenCV同态滤波
    重复文件重新创建
    Consider using the `--user` option or check the permissions.
    错误:pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.
    python tkinter模版
    tkinter页面卡死
    视频下载
    tkinter学习系列(三)之Label控件
    Entry小部件:
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/14106432.html
Copyright © 2011-2022 走看看