欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

angular4自定義組件非input元素實(shí)現(xiàn)ngModel雙向數(shù)據(jù)綁定的方法

 更新時(shí)間:2018年12月28日 09:57:16   作者:Amor丶Diamond  
這篇文章主要介紹了angular4自定義組件非input元素實(shí)現(xiàn)ngModel雙向數(shù)據(jù)綁定的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

在angular里我們一般都是給input元素添加[(ngModel)]="value"實(shí)現(xiàn)數(shù)據(jù)雙向綁定,如果想實(shí)現(xiàn)自定義的組件上實(shí)現(xiàn)ngModel雙向數(shù)據(jù)綁定應(yīng)該怎么辦吶。。。

網(wǎng)上找了一下,沒看懂記錄一下。

場(chǎng)景:組件能獲取父組件通過ngModel綁定的值,能通過ngModel改變父組件對(duì)應(yīng)的數(shù)據(jù)。如下代碼:

<app-child [(ngModel])="appData"></app-child>

1、先貼出效果圖:

2、下面是app-child組件的代碼:

import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
 selector: 'app-child',
 templateUrl: './child.component.html',
 styleUrls: ['./child.component.css'],
 providers: [{
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => ChildComponent),
  multi: true
 }]
})
export class ChildComponent implements ControlValueAccessor {
 constructor() { }
 _data: any;
 add () {
  this.childData ++;
 }
 change = (value: any) => {}; // 先定義一個(gè)方法,很重要,用于接收registerOnChange()方法里傳遞回來的方法,然后通過這個(gè)方法就能通知到外部組件數(shù)據(jù)更新。
 set childData(value: number) { // childData被更改走該方法
  this._data = value;
  this.change(this._data); // 將更新后的數(shù)據(jù)通知到外部組件
 }
 get childData() { // 頁(yè)面或者方法里面有調(diào)用childData就會(huì)走該方法
  return this._data;
 }
 writeValue(val): void { // 初始化時(shí),獲取并監(jiān)聽父組件通過ngModel傳遞進(jìn)來的數(shù)據(jù)
  if (val) {
   this._data = val;
  }
 }
 registerOnChange(fn: any): void { // 初始化后,執(zhí)行該方法,并保存控件接收到 change 事件后,調(diào)用的函數(shù)
  this.change = fn;
 }
 registerOnTouched(fn: any): void {
 }
}

3、下面開始說下實(shí)現(xiàn)的過程吧:

如果添加ngModel后報(bào)如下錯(cuò)誤,檢查組件對(duì)應(yīng)的Module文件有沒有導(dǎo)入FormsModule

import { FormsModule } from '@angular/forms';
@NgModule({
 ...
 imports: [
  ...,
  FormsModule
 ],
 ...
})

import FormsModule后,控制臺(tái)任然會(huì)報(bào)錯(cuò):

這是因?yàn)槲覀冃枰谑褂胣gModel的組件里實(shí)現(xiàn)ControlValueAccessor的接口方法。

先引入和使用我們必須使用的配置:

import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
 selector: 'app-child',
 templateUrl: './child.component.html',
 styleUrls: ['./child.component.css'],
 providers: [{
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => ChildComponent), // 這里的組件名為當(dāng)前組件的名字
  multi: true
 }]
})
export class ChildComponent implements ControlValueAccessor {
 constructor() { }
 childData = 2;
}

處理完成后控制臺(tái)的報(bào)錯(cuò)信息已經(jīng)改變:

這是因?yàn)镃ontrolValueAccessor的接口有幾個(gè)必須存在的方法,會(huì)自動(dòng)去調(diào)用:

 writeValue(val): void {
 }
 registerOnChange(fn: any): void {
 }
 registerOnTouched(fn: any): void {
 }
  • 初始化的時(shí)候調(diào)用  writeValue()  方法,將會(huì)使用表單模型中對(duì)應(yīng)的初始值作為參數(shù)(也就是ngModel里的值)。
  • registerOnChange() 可以用來通知外部,組件已經(jīng)發(fā)生變化。
  • registerOnTouched() 方法用于設(shè)置當(dāng)控件接收到 touched 事件后,調(diào)用的函數(shù)。

知道了這三個(gè)方法后,我們就可以在writeValue方法里給組件設(shè)置父組件通過ngModel傳遞過來的值了。如:

writeValue(val): void {
 if (val) {
  this.childData = val;
 }
}

那么怎么將組件里更新的數(shù)據(jù)傳遞給父組件吶。

registerOnChange(fn: any): void { // 初始化后,執(zhí)行該方法,并保存控件接收到 change 事件后,調(diào)用的函數(shù)
 this.change = fn;
}

writeValue()方法后就會(huì)執(zhí)行registerOnChange()方法,我們就是通過該方法傳遞回來的方法參數(shù)來通知到外部組件數(shù)據(jù)更新的,所以我們要在最開始就定義一個(gè)方法來接收。

change = (value: any) => {}; 
// 先定義一個(gè)方法,很重要,用于接收registerOnChange()方法里傳遞回來的方法,然后通過這個(gè)方法就能通知到外部組件數(shù)據(jù)更新。

然后就可以通過change方法通知外部組件了

set childData(value: number) { // childData被更改走該方法
 this._data = value;
 this.change(this._data); // 將更新后的數(shù)據(jù)通知到外部組件
}

最開始貼出來的代碼,中間使用了set 和get去處理了數(shù)據(jù),在get childData()方法里打斷點(diǎn)發(fā)現(xiàn)會(huì)執(zhí)行很多次該方法,其實(shí)也可以修改成通過更新數(shù)據(jù)的時(shí)候就直接調(diào)用change()方法來通知外部組件數(shù)據(jù)更新,如下:

import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
 selector: 'app-child',
 templateUrl: './child.component.html',
 styleUrls: ['./child.component.css'],
 providers: [{
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => ChildComponent),
  multi: true
 }]
})
export class ChildComponent implements ControlValueAccessor {
 constructor() { }
 _data: any;
 childData = 1;
 add () {
  this.childData ++;
  this.change(this.childData);
 }
 change = (value: any) => {}; // 先定義一個(gè)方法,很重要,用于接收registerOnChange()方法里傳遞回來的方法,然后通過這個(gè)方法就能通知到外部組件數(shù)據(jù)更新。
 writeValue(val): void { // 初始化時(shí),獲取并監(jiān)聽父組件通過ngModel傳遞進(jìn)來的數(shù)據(jù)
  if (val) {
   this.childData = val;
  }
 }
 registerOnChange(fn: any): void { // 初始化后,執(zhí)行該方法,并保存控件接收到 change 事件后,調(diào)用的函數(shù)
  this.change = fn;
 }
 registerOnTouched(fn: any): void {
 }
}

中間不用使用get和set,不知道兩種方法哪種更好。

其實(shí)通過子組件通知父級(jí)組件數(shù)據(jù)更新,可以使用@Input和@Output來實(shí)現(xiàn)的,如果是@Input獲取的父級(jí)組件的數(shù)據(jù),父級(jí)組件數(shù)據(jù)更新,子組件需要在ngOnChanges生命周期里去監(jiān)聽對(duì)應(yīng)的數(shù)據(jù)變更并處理相應(yīng)的邏輯。

不過在自定義組件上使用ngModel實(shí)現(xiàn)數(shù)據(jù)的雙向綁定還可以用作表單處理上,比如表單模板和表單驗(yàn)證。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論