\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 ];