ng-zorro-antd 结构窥探
项目目录结构
cdk
Component Development Kit
The Component Dev Kit (CDK) is a set of behavior primitives for building UI components.
参考链接
components
存放组件以及命令的目录
Core
项目组件中的公共方法集合地
util
里面封装了框架中使用到的共用组件和方法
-
Array
export function toArray<T>(value: T | T[]): T[] { let ret: T[]; if (value == null) { ret = []; } else if (!Array.isArray(value)) { ret = [value]; } else { ret = value; } return ret; } export function arraysEqual<T>(array1: T[], array2: T[]): boolean { if (!array1 || !array2 || array1.length !== array2.length) { return false; } const len = array1.length; for (let i = 0; i < len; i++) { if (array1[i] !== array2[i]) { return false; } } return true; } export function shallowCopyArray<T>(source: T[]): T[] { return source.slice(); }
-
Check
export function isNotNil<T>(value: T): value is NonNullable<T> { return typeof value !== 'undefined' && value !== null; } export function isNil(value: unknown): value is null | undefined { return typeof value === 'undefined' || value === null; } /** * Examine if two objects are shallowly equaled. */ export function shallowEqual(objA?: any, objB?: any): boolean { if (objA === objB) { return true; } if (typeof objA !== 'object' || !objA || typeof objB !== 'object' || !objB) { return false; } const keysA = Object.keys(objA); const keysB = Object.keys(objB); if (keysA.length !== keysB.length) { return false; } const bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB); // tslint:disable-next-line:prefer-for-of for (let idx = 0; idx < keysA.length; idx++) { const key = keysA[idx]; if (!bHasOwnProperty(key)) { return false; } if (objA[key] !== objB[key]) { return false; } } return true; } export function isNonEmptyString(value: any): boolean { return typeof value === 'string' && value !== ''; }
-
convert
其中使用到了angular中的cdk/coercion
/** * Get the function-property type's value */ export function valueFunctionProp<T>(prop: FunctionProp<T> | T, ...args: NzSafeAny[]): T { return typeof prop === 'function' ? (prop as FunctionProp<T>)(...args) : prop; } function propDecoratorFactory<T, D>(name: string, fallback: (v: T) => D): (target: NzSafeAny, propName: string) => void { function propDecorator(target: NzSafeAny, propName: string, originalDescriptor?: TypedPropertyDescriptor<NzSafeAny>): NzSafeAny { const privatePropName = `$$__${propName}`; if (Object.prototype.hasOwnProperty.call(target, privatePropName)) { warn(`The prop "${privatePropName}" is already exist, it will be overrided by ${name} decorator.`); } 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; } /** * Input decorator that handle a prop to do get/set automatically with toBoolean * * Why not using @InputBoolean alone without @Input? AOT needs @Input to be visible * * @howToUse * ``` * @Input() @InputBoolean() visible: boolean = false; * * // Act as below: * // @Input() * // get visible() { return this.__visible; } * // set visible(value) { this.__visible = value; } * // __visible = false; * ``` */ export function InputBoolean(): NzSafeAny { return propDecoratorFactory('InputBoolean', toBoolean); } export function InputCssPixel(): NzSafeAny { return propDecoratorFactory('InputCssPixel', toCssPixel); } export function InputNumber(fallbackValue?: NzSafeAny): NzSafeAny { return propDecoratorFactory('InputNumber', (value: string | number) => toNumber(value, fallbackValue)); }
animation
ng-zorro-ant中使用的动画
<div
class="ant-collapse-content"
[class.ant-collapse-content-active]="nzActive"
[@.disabled]="noAnimation?.nzNoAnimation"
[@collapseMotion]="nzActive ? 'expanded' : 'hidden'"
>
<div class="ant-collapse-content-box">
<ng-content></ng-content>
</div>
</div>
自己使用动画
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { collapseMotion, fadeMotion, moveUpMotion } from 'ng-zorro-antd';
@Component({
selector: 'app-animations',
templateUrl: './animations.component.html',
styleUrls: ['./animations.component.less'],
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [collapseMotion],
})
export class AnimationsComponent implements OnInit {
isActive = false;
constructor() { }
ngOnInit() {}
}
点击.fade-header content内容就会展开
<div class="fade-header" (click)="isActive=!isActive">
<i nz-icon [nzType]="isActive ? 'down' : 'up'" nzTheme="outline"></i> Collapsed Header
</div>
<div class="content" [@collapseMotion]="isActive ? 'expanded' : 'hidden' ">
<p>content</p>
<p>content</p>
</div>
message
tree
nz-tree-base-util.ts
export function isCheckDisabled(node: NzTreeNode): boolean {
const { isDisabled, isDisableCheckbox } = node;
return !!(isDisabled || isDisableCheckbox);
}
“!”是逻辑与运算,并且可以与任何变量进行逻辑与将其转化为布尔值,“!!”则是逻辑与的取反运算,尤其后者在判断类型时代码简洁高效,省去了多次判断null、undefined和空字符串的冗余代码
var a;
if(a!=null&&typeof(a)!=undefined&&a!=''){
//a有内容才执行的代码
}
// 等价于
if(!!a){
//a有内容才执行的代码...
}
Color
内置了几种常用的颜色
export const presetColors = [
'pink',
'red',
'yellow',
'orange',
'cyan',
'green',
'blue',
'purple',
'geekblue',
'magenta',
'volcano',
'gold',
'lime'
] as const;
export type NzPresetColor = typeof presetColors[number];
export function isPresetColor(color: string): color is NzPresetColor {
return presetColors.indexOf(color as NzSafeAny) !== -1;
}