您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關(guān)angular4怎么通過(guò)自定義組件實(shí)現(xiàn)ngModel雙向數(shù)據(jù)綁定,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
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()方法里傳遞回來(lái)的方法,然后通過(guò)這個(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)聽(tīng)父組件通過(guò)ngModel傳遞進(jìn)來(lái)的數(shù)據(jù) if (val) { this._data = val; } } registerOnChange(fn: any): void { // 初始化后,執(zhí)行該方法,并保存控件接收到 change 事件后,調(diào)用的函數(shù) this.change = fn; } registerOnTouched(fn: any): void { } }
3、下面開(kāi)始說(shuō)下實(shí)現(xiàn)的過(guò)程吧:
如果添加ngModel后報(bào)如下錯(cuò)誤,檢查組件對(duì)應(yīng)的Module文件有沒(méi)有導(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() 可以用來(lái)通知外部,組件已經(jīng)發(fā)生變化。
registerOnTouched() 方法用于設(shè)置當(dāng)控件接收到 touched 事件后,調(diào)用的函數(shù)。
知道了這三個(gè)方法后,我們就可以在writeValue方法里給組件設(shè)置父組件通過(guò)ngModel傳遞過(guò)來(lái)的值了。如:
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()方法,我們就是通過(guò)該方法傳遞回來(lái)的方法參數(shù)來(lái)通知到外部組件數(shù)據(jù)更新的,所以我們要在最開(kāi)始就定義一個(gè)方法來(lái)接收。
change = (value: any) => {}; // 先定義一個(gè)方法,很重要,用于接收registerOnChange()方法里傳遞回來(lái)的方法,然后通過(guò)這個(gè)方法就能通知到外部組件數(shù)據(jù)更新。
然后就可以通過(guò)change方法通知外部組件了
set childData(value: number) { // childData被更改走該方法 this._data = value; this.change(this._data); // 將更新后的數(shù)據(jù)通知到外部組件 }
最開(kāi)始貼出來(lái)的代碼,中間使用了set 和get去處理了數(shù)據(jù),在get childData()方法里打斷點(diǎn)發(fā)現(xiàn)會(huì)執(zhí)行很多次該方法,其實(shí)也可以修改成通過(guò)更新數(shù)據(jù)的時(shí)候就直接調(diào)用change()方法來(lái)通知外部組件數(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()方法里傳遞回來(lái)的方法,然后通過(guò)這個(gè)方法就能通知到外部組件數(shù)據(jù)更新。 writeValue(val): void { // 初始化時(shí),獲取并監(jiān)聽(tīng)父組件通過(guò)ngModel傳遞進(jìn)來(lái)的數(shù)據(jù) if (val) { this.childData = val; } } registerOnChange(fn: any): void { // 初始化后,執(zhí)行該方法,并保存控件接收到 change 事件后,調(diào)用的函數(shù) this.change = fn; } registerOnTouched(fn: any): void { } }
看完上述內(nèi)容,你們對(duì)angular4怎么通過(guò)自定義組件實(shí)現(xiàn)ngModel雙向數(shù)據(jù)綁定有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。