• ngzorro UI源码技巧(一)


    在Angular 中转译

    转移: 将代码从一种高级语言转换为另一种高级语言。

    编译:将代码从高级语言转换为机器级语言

    每个 Angular 项目都有一个名为tsconfig.json的文件,其中包含将 .js 文件转换为 .ts 文件的设置。

    tsconfig.json官网地址

    JIT和AOT编译的区别

    • JIT 编译是在应用程序运行时完成的,而 AOT 编译是在构建过程中完成的。

    angular-cdk-dir

    模块注入

    import {BidiModule} from '@angular/cdk/bidi';
    
      imports: [ BidiModule, ]
    

    文本方向

    <p [dir]="dir">
      可以动态切换方向
    </p>
    
    // 'ltr'(左到右)| 'rtl' (右到左)
      dir = "rtl";
    
    类似 text-align="left|right"   只是几个自带的盒子都会变成这样
    

    可以把整个组件都添加这个效果

    监听

    <app-report2  [dir]="dir"></app-report2>
      dir: Direction = 'rtl';
    

     constructor(
         private directionality: Directionality
      ) {}
    
      ngOnInit(): void {
        this.directionality.change?.subscribe((direction: Direction) => {
          console.log(direction,'被改变了111');
        });
      }
    

    @Component

    封装策略

    @Component({
        encapsulation: ViewEncapsulation.Emulated  默认
    })
    
    • ViewEncapsulation.Emulated:应用修改后的组件样式以模拟原生 Shadow DOM CSS 封装行为。
    • ViewEncapsulation.None:在没有任何封装的情况下全局应用组件样式。
    • ViewEncapsulation.ShadowDom: 使用浏览器原生的 Shadow DOM API 来封装样式。

    如果我们想受到上级的影响可以使用ViewEncapsulation.None

    @Input 父传子进行过滤筛选

    <app-report2 [bool]="1" ></app-report2>
    
      @Input()
      @InputBoolean()
      bool:any = false;
    

    InputBoolean 工具库, 我们如果写给别人用的组件, 不可能别人给了一个不符合我们规定的属性,我们就给他报错, 如果给的是其他类型, 我们可以把他强转到我们需要的类型,进行处理, InputBoolean 内部做了get,set 监控, 避免父级修改了, 儿子可以重新检测到

    
    import {coerceBooleanProperty} from '@angular/cdk/coercion';
    
    // 添加get set 当元素修改的时候重新执行
    function propDecoratorFactory<T, D>(
      name: string,
      fallback: (v: T) => D
    ): (target: any, propName: string) => void {
    
      function propDecorator(
        target: any,
        propName: string,
        originalDescriptor?: TypedPropertyDescriptor<any>
      ): any {
        const privatePropName = `$$__zorroPropDecorator__${propName}`;
        console.log(target);
    
        Object.defineProperty(target, privatePropName, {
          configurable: true,
          writable: true
        });
    
        return {
          get(): string {
            return originalDescriptor && originalDescriptor.get
              ? originalDescriptor.get.bind(this)()
              : this[privatePropName];
          },
          set(value: T): void {
            if (originalDescriptor && originalDescriptor.set) {
              originalDescriptor.set.bind(this)(fallback(value));
            }
            this[privatePropName] = fallback(value);
          }
        };
      }
    
      return propDecorator;
    }
    // 我们可以自己写自定义的
    export function InputBoolean(): any {
      return propDecoratorFactory('InputBoolean', toBoolean);
    }
    // 我们可以自己写自定义的
    export function toBoolean(value: boolean | string): boolean {
      return coerceBooleanProperty(value);
    }
    

    host 技巧

    组件的最外层添加class或者属性

    @Component({
      selector: 'app-report2',
      templateUrl: './report2.component.html',
      styleUrls: ['./report2.component.scss'],
      host:{
        class:'ant-xxx',
        '[class.aaa]':`bool`,
        '[class.bbb]':`bool==true`,
      }
    })
    
    bool 是下面组件使用的一个变量
    

    tabindex

    div添加获取焦点失去焦点属性

    <div  tabindex="-1" (blur)="changeBlur()">kkkkkkkk</div>
    

    startWith

      b = new Subject<string>();
      this.b.pipe(
          startWith('xxx')
        ).subscribe(console.log)
    

    这样我们就不一样要使用BehaviorSubject

    exportAs 别名的使用

    @Component({
      selector: 'button[nz-button], a[nz-button]',
      exportAs: 'nzButton',
    })
    

    使用

    <button nz-button nzType="primary" #aaa='nzButton'>Primary Button</button>
    
      @ViewChild('aaa') aaa!: NzButtonComponent;
      ngAfterViewInit() {
        console.log(this.aaa); // NzButtonComponent
      }  	
    

    我们在angular.js可能用的比较多

    <input type="text" [(ngModel)]="str" #strA="ngModel">
    
      @ViewChild('strA') strA!: NgModel;
      ngAfterViewInit() {
        if(this.strA){
            this.strA.control.valueChanges// 检测变化
        }
      }  
    

    stopPropagation与stopImmediatePropagation的区别

    event.stopPropagation();阻止事件冒泡

    event.stopImmediatePropagation(); 阻止事件冒泡并且阻止该元素上同事件类型的监听器被触发。

     可以同时用这两个, 用在按钮上
     event.preventDefault();
     event.stopImmediatePropagation();
    

    默认我们阻止默认行为和停止事件传播, 所以不需要Angular运行变更检测

    当我们点击按钮的时候,如果是禁用的是a链接或者loading开启的时候,就类似禁止点击

    ngOnInit(): void {
     this.ngZone.runOutsideAngular(() => {
          fromEvent<MouseEvent>(this.elementRef.nativeElement, 'click', { capture: true })
            .pipe(takeUntil(this.destroy$))
            .subscribe(event => {
              if ((this.disabled && (event.target as HTMLElement)?.tagName === 'A') || this.nzLoading) {
                event.preventDefault();
                event.stopImmediatePropagation();
              }
            });
        });
      }
    

    开发环境和打包后的资源处理

    我们打包后想引入那时候的本地网址的地址, 和本地环境进行区别

    类似我们需要的本地自定义图标

    导入模块

    app.module.ts

     providers: [
        {
          provide: APP_BASE_HREF,
          useFactory: (s: PlatformLocation) => s.getBaseHrefFromDOM(),
          deps: [PlatformLocation],
        },
     ]    
    

    app.component.ts

    constructor(
        @Inject(APP_BASE_HREF) href: string
      ) {
        this.nzIconService.fetchFromIconfont({
          scriptUrl: environment.production ? href + '/assets/线上' : '../assets/本地用相对路径',
        });
    

    自定义图标的使用

    <i nz-icon [nzIconfont]="'icon-tuichu'"></i>
    
  • 相关阅读:
    【LOJ6041】「雅礼集训 2017 Day7」事情的相似度(用LCT维护SAM的parent树)
    【BZOJ1171】大sz的游戏(线段树+单调队列)
    2019年4月训练记录(4.07~4.22)
    【BZOJ4766】文艺计算姬(prufer序列)
    【BZOJ4573】[ZJOI2016] 大森林(LCT)
    2019.03.19 ZJOI2019模拟赛 解题报告
    【牛客挑战赛30D】小A的昆特牌(组合问题抽象到二维平面)
    【洛谷2624】[HNOI2008] 明明的烦恼(Python+利用prufer序列结论求解)
    【洛谷2290】[HNOI2004] 树的计数(Python+利用prufer序列结论求解)
    初识prufer序列
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/15929017.html
Copyright © 2020-2023  润新知