详解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 相关文章推荐
JQUERY设置IFRAME的SRC值的代码
Nov 30 Javascript
JS仿百度搜索自动提示框匹配查询功能
Nov 21 Javascript
JavaScript运行时库属性一览表
Mar 14 Javascript
我的Node.js学习之路(四)--单元测试
Jul 06 Javascript
jQuery实现向下滑出的平滑下拉菜单效果
Aug 21 Javascript
jqPlot jQuery绘图插件的使用
Jun 18 Javascript
轻松掌握JavaScript享元模式
Aug 27 Javascript
jq给页面添加覆盖层遮罩的实例
Feb 16 Javascript
利用纯JS实现像素逐渐显示的方法示例
Aug 14 Javascript
Vue中添加手机验证码组件功能操作方法
Dec 07 Javascript
详解vue-cli 接口代理配置
Dec 13 Javascript
echarts同一页面中四个图表切换的js数据交互方法示例
Jul 03 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
解析argc argv在php中的应用
2013/06/24 PHP
thinkphp中多表查询中防止数据重复的sql语句(必看)
2016/09/22 PHP
php实现的读取CSV文件函数示例
2017/02/07 PHP
PHP实现基于栈的后缀表达式求值功能
2017/11/10 PHP
PHP有序表查找之二分查找(折半查找)算法示例
2018/02/09 PHP
document.open() 与 document.write()的区别
2007/08/13 Javascript
jQuery div层的放大与缩小简单实现代码
2013/03/28 Javascript
关于JS中的闭包浅谈
2013/08/23 Javascript
JS网页图片按比例自适应缩放实现方法
2014/01/15 Javascript
javascript数组操作总结和属性、方法介绍
2014/04/05 Javascript
jqPlot jQuery绘图插件的使用
2016/06/18 Javascript
js阻止冒泡和默认事件(默认行为)详解
2016/10/20 Javascript
node.js 抓取代理ip实例代码
2017/04/30 Javascript
Bootstrap fileinput文件上传预览插件使用详解
2017/05/16 Javascript
实例详解JSON取值(key是中文或者数字)方式
2017/08/24 Javascript
vue组件父与子通信详解(一)
2017/11/07 Javascript
vue几个常用跨域处理方式介绍
2018/02/07 Javascript
Vue 进阶之路(三)
2019/04/18 Javascript
微信小程序点击列表跳转到对应详情页过程解析
2019/09/26 Javascript
JS正则表达式验证密码强度
2020/03/18 Javascript
[01:46]辉夜杯—打造中国DOTA新格局
2015/12/25 DOTA
[49:28]VP vs Optic 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python中文件操作简明介绍
2015/04/13 Python
Python脚本获取操作系统版本信息
2016/12/17 Python
利用python修改json文件的value方法
2018/12/31 Python
Python基础之字符串常见操作经典实例详解
2020/02/26 Python
Python动态强类型解释型语言原理解析
2020/03/25 Python
django queryset相加和筛选教程
2020/05/18 Python
浅谈keras使用中val_acc和acc值不同步的思考
2020/06/18 Python
Python图像读写方法对比
2020/11/16 Python
appium+python自动化配置(adk、jdk、node.js)
2020/11/17 Python
Python爬虫分析微博热搜关键词的实现代码
2021/02/22 Python
用pip给python安装matplotlib库的详细教程
2021/02/24 Python
医学生自荐信范文
2015/03/05 职场文书
敬老院活动感想
2015/08/07 职场文书
mysql字符串截取函数小结
2021/04/05 MySQL