Angular2中Input和Output用法及示例


Input相當於指令的值綁定,無論是單向的(@)還是雙向的(=)。丟失將父作用域的值“輸入”到子作用域中, 然后子作用域進行相關處理。

Output 相當於指令的方法綁定,子作用域觸發事件執行響應函數, 而響應函數方法體則位於父作用域中, 相當於將事件“輸出”到父作用域中, 在父作用域中處理。 

看個angular2示例吧,我們自定義一個numberInput component,獲取父作用域的值或者屬性,然后在鼠標離開的時候調用父組件的方法驗證

import {
    Component, Input, Output, OnInit, ExistingProvider, forwardRef,
    AfterViewInit, ElementRef, ViewChild, ViewContainerRef, ChangeDetectorRef, Optional, EventEmitter
} from '@angular/core'
import {
    NgModel, ControlValueAccessor, NG_VALUE_ACCESSOR, NgForm, FormControl,
    ValidatorFn, ValidationErrors
} from '@angular/forms'
import { InputBase, existingProvider } from '../../inputBase'
import { Observable } from 'rxjs'
declare var $: any;

@Component({
    selector: 'cm-number',
    templateUrl: 'numberInput.component.html',
    styleUrls: ["./numberInput.component.css"],
    providers: [existingProvider(NumericInputComponent)]
})
export class NumericInputComponent extends InputBase implements OnInit {

    @ViewChild("input")
    input: ElementRef;
    ngOnInit() {
        Observable.merge(
            Observable.fromEvent<Event>(this.input.nativeElement, "input"),
            Observable.fromEvent<Event>(this.input.nativeElement, "blur"),
            Observable.fromEvent<Event>(this.input.nativeElement, "change")
        ).subscribe(e => {
            e.stopPropagation();
            e.stopImmediatePropagation();
            let p = e.target as HTMLInputElement;
            let val = this.format(p.value);
            if (val !== p.value) {
                p.value = val;
            }
            if (val != this.model.value) {
                if (val == undefined || val.trim() === "") {
                    this.onChange(undefined);
                } else {
                    this.onChange(parseFloat(val));
                }
            }
        });

        if (this.model != null) {
            var fn: ValidatorFn = (c) => {
                var errors: ValidationErrors = {};

                if ((this.hasEqualOperatorForMin && parseFloat(this.internalValue) < parseFloat(this.min.toString()))
                    || (!this.hasEqualOperatorForMin && parseFloat(this.internalValue) <= parseFloat(this.min.toString()))
                    || parseFloat(this.internalValue) > parseFloat(this.max.toString())) {

                    errors.dose = true;

                }
                return errors;
            }
            this.model.control.setValidators(fn);
        }
    }

    private get internalValue() {
        let val = (<HTMLInputElement>this.input.nativeElement).value;
        if (!val) return undefined;
        val = val.trim();
        if (val == "") return undefined;
        return val;
    }

    private format(val: string) {
        while (true) {
            let newVal = val.replace(/[^0-9.-]/g, '');
            if (this.allowFloat) {
                newVal = newVal.replace(/(\..*)\./g, '$1');
            }
            else {
                newVal = newVal.replace(/(.*)\./g, '$1');
            }

            if (!this.allowNegative) {
                newVal = newVal.replace(/-/g, '');
            }
            else {
                newVal = newVal.replace(/^-(-.*)/g, '$1');
                newVal = newVal.replace(/(.+)-/g, '$1');
            }

            newVal = newVal.replace(/^0+([0-9].*)/g, '$1');
            newVal = newVal.replace(/^0+(0\..*)/g, '$1');
            if (newVal === val) break;
            val = newVal;
        }
        return val;
    }

    public _value: string;
    @Input() maxlength: number;
    @Input() readonly: boolean = false;
    @Input() allowFloat: boolean = true;
    @Input() min: number = 0;
    @Input() max: number = 99999;
    @Input()
    public get value() {
        return this._value;
    }
    public set value(val: string) {
        this._value = val;
        if (val == undefined || val.trim() == "") {
            this.onChange(undefined);
        }
        else {
            this.onChange(parseFloat(this._value));
        }
    }

    public writeValue(obj: any) {
        obj = obj == undefined ? "" : obj;
        (this.input.nativeElement as HTMLInputElement).value = obj;
    }

    @Output()
    public onblur: EventEmitter<any> = new EventEmitter<any>();
    blur(e: Event) {
        this.onblur.emit($(e.target).val());
    }
}

 就舉一個例子:

我們在父作用域中使用的時候, 可以這樣賦值:

其實number input component 中, 我們會根據 allowFloat 的值,來決定是否允許輸入小數。

ok, 以上是Input的示例。

Output一般都是一個EventEmitter的實例,使用實例的emit方法將參數emit到父組件中,觸發父組件的事件。

然后父組件監聽到該事件的發生,執行對應的處理函數。

這里之所以要自定義一次 blur  事件(EventEmitter), 是因為在 ngOnInit()中已經對blur 事件做過處理,這樣父控件中就會被阻止掉,如果父控件中要用到blur 事件的話, 就可以用這種方式來做,我們自定義一個叫onBlur 的事件,然后在父控件中去實現內部邏輯。

是不是很簡單啊。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM