\angular-master\packages\common\src\directivescss
@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>
<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() { } }
@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用的是全局的html
为了使您的应用程序能够与服务器端渲染一块儿使用,我建议您不只使用窗口直通令牌,并且还以SSR友好的方式建立此令牌,而无需彻底引用
window
。Angular具备DOCUMENT
用于访问的内置令牌document
。git看了写大佬写的github
export const WINDOW=new InjectionToken<Window>( 'return reference to window', {providedIn:'platform',factory:()=>window} )有个库, 本地Web API的高质量轻量级包装器web
能够看看源码学习下api
而后把咱们写好的
WINDOW
注入到页面里面,代替咱们写的window
数组
conststructor(@Inject(WINDOW) private window) 替换以前的改为 this.window
有时间好好研究依赖注入,服务那块服务器
<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 ) { } }
将一个或者多个组件插入视图中app
@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;
@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() { } }
<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 ];