详解Angular中实现自定义组件的双向绑定的两种方法


Posted in Javascript onNovember 23, 2018

在 Angular 中,对于表单元素,通过 [(ngModel)] 即可以简单地实现双向绑定。对于自定义组件而言,希望实现同样的效果可以怎么做呢?

1 实现自定义组件的 ngModel 指令

如果希望自定义组件能够具有与表单元素相同的 ngModel 效果,可以通过在组件内实现 ControlValueAccessor 接口达到目的。

对于 [(ngModel)] ,需要至少实现该接口的如下方法:

interface ControlValueAccessor { 
 writeValue(obj: any): void
 registerOnChange(fn: any): void
 registerOnTouched(fn: any): void
}

最简单的核心实现示例参考如下。

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

@Component({
 selector: 'custom-input',
 template: `<input [(ngModel)]="value"/>`,
 providers: [
  {
   provide: NG_VALUE_ACCESSOR,
   useExisting: forwardRef(() => UnionInputComponent),
   multi: true
  }
 ]
})
export class CustomInputComponent implements ControlValueAccessor {
 constructor() { }
 private innerValue: any = '';
 private onTouchedCallback: () => void = function () { };
 private onChangeCallback: (_: any) => void = function () { };

 get value(): any {
  return this.innerValue;
 }
 set value(v: any) {
  if (v !== this.innerValue) {
   this.innerValue = v;
   this.onChangeCallback(v);
  }
 }
 /**
  * model view -> view value
  */
 writeValue(value: any) {
  if (value !== this.innerValue) {
   this.innerValue = value;
  }
 }
 /**
  * view value ->model value
  */
 registerOnChange(fn: any) {
  this.onChangeCallback = fn;
 }
 registerOnTouched(fn: any) {
  this.onTouchedCallback = fn;
 }
}

2 使用 get/set 关键字实现父子组件的双向绑定

其实实现双向绑定内部的本质原理就是父子组件的事件绑定机制。简单举例如下。

2.1 自定义子组件定义

import { Input, Output, Component, EventEmitter } from '@angular/core';

@Component({
 selector: 'custom-input',
 template: `<input [(ngModel)]="innerValue"/>`,
})
export class CustomInputComponent {
 innerValue;

 @Input()
 get twoWayModel() {
  return this.innerValue;
 }
 set twoWayModel(val) {
  this.innerValue = val;
  this.twoWayModelChange.emit(this.innerValue);
 }
 @Output() twoWayModelChange: EventEmitter<string> = new EventEmitter</string><string>();
}

2.2 使用自定义组件

在需要使用组件的地方,通过 [(twoWayModel)] 即可实现双向绑定的效果。

import { Input, Output } from '@angular/core';
import { Component, forwardRef, Input } from '@angular/core';
@Component({
 selector: 'custom-input',
 template: `<custom -input [(twoWayModel)]="inputValue" (twoWayModelChange)="onInputValueChange($event)"></custom>`
})
export class abcComponent {
 inputValue;
 onInputValueChange(val) {
  console.log(val);
  console.log(val === this.inputValue); // true
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js传值 判断
Oct 26 Javascript
JQuery 1.4 中的Ajax问题
Jan 23 Javascript
深入分析js中的constructor和prototype
Apr 07 Javascript
js jq 单击和双击区分示例介绍
Nov 05 Javascript
JavaScript使用循环和分割来替换和删除元素实例
Oct 13 Javascript
JavaScript中的alert()函数使用技巧详解
Dec 29 Javascript
Javascript实现div层渐隐效果的方法
May 30 Javascript
JavaScript 浏览器兼容性总结及常用浏览器兼容性分析
Mar 30 Javascript
cocos2dx+lua实现橡皮擦功能
Dec 20 Javascript
JavaScript代码调试方法实例小结
Jan 05 Javascript
vue-cli3使用 DllPlugin 实现预编译提升构建速度
Apr 24 Javascript
Vite + React从零开始搭建一个开源组件库
Jun 25 Javascript
Vue.js组件间通信方式总结【推荐】
Nov 23 #Javascript
vue-cli 2.*中导入公共less文件的方法步骤
Nov 22 #Javascript
vue全局使用axios的方法实例详解
Nov 22 #Javascript
vue中的ref和$refs的使用
Nov 22 #Javascript
浅析vue 函数配置项watch及函数 $watch 源码分享
Nov 22 #Javascript
原生JS实现手动轮播图效果实例代码
Nov 22 #Javascript
js实现按钮开关单机下拉菜单效果
Nov 22 #Javascript
You might like
php入门学习知识点七 PHP函数的基本应用
2011/07/14 PHP
php 操作数组(合并,拆分,追加,查找,删除等)
2012/07/20 PHP
php生成网页桌面快捷方式
2017/05/05 PHP
基于jquery的自定义鼠标提示效果 jquery.toolTip
2010/11/14 Javascript
Javascript动态绑定事件的简单实现代码
2010/12/25 Javascript
JS正则表达式获取分组内容的方法详解
2013/11/15 Javascript
调整小数的格式保留小数点后两位
2014/05/14 Javascript
JavaScript中使用typeof运算符需要注意的几个坑
2014/11/08 Javascript
zepto中使用swipe.js制作轮播图附swipeUp,swipeDown不起效果问题
2015/08/27 Javascript
js文字横向滚动特效
2015/11/11 Javascript
ES6新特性六:promise对象实例详解
2017/04/21 Javascript
javascript 判断一个对象为数组的方法
2017/05/03 Javascript
JS实现网页烟花动画效果
2020/03/10 Javascript
jQuery实现飞机大战小游戏
2020/07/05 jQuery
Python中AND、OR的一个使用小技巧
2015/02/18 Python
python实现搜索本地文件信息写入文件的方法
2016/02/22 Python
python基于itchat实现微信群消息同步机器人
2017/02/27 Python
Python中shutil模块的学习笔记教程
2017/04/04 Python
深入理解Django-Signals信号量
2019/02/19 Python
Python面向对象之继承和多态用法分析
2019/06/08 Python
python 画3维轨迹图并进行比较的实例
2019/12/06 Python
Python 解析pymysql模块操作数据库的方法
2020/02/18 Python
python 日志 logging模块详细解析
2020/03/31 Python
tensorflow常用函数API介绍
2020/04/19 Python
Python的控制结构之For、While、If循环问题
2020/06/30 Python
python利用os模块编写文件复制功能——copy()函数用法
2020/07/13 Python
利用python绘制中国地图(含省界、河流等)
2020/09/21 Python
python 绘制场景热力图的示例
2020/09/23 Python
python 合并多个excel中同名的sheet
2021/01/22 Python
HTML5之多线程(Web Worker)
2019/01/02 HTML / CSS
蔻驰法国官网:COACH法国
2018/11/14 全球购物
酒店开业策划方案
2014/06/02 职场文书
2015年秋季新学期寄语
2015/03/25 职场文书
爱心捐款活动总结
2015/05/09 职场文书
python flask开发的简单基金查询工具
2021/06/02 Python
Python何绘制带有背景色块的折线图
2022/04/23 Python