ng-zorro 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>
posted @ 2022-02-23 19:58  猫神甜辣酱  阅读(390)  评论(0编辑  收藏  举报