详解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 相关文章推荐
原生javascript实现图片轮播效果代码
Sep 03 Javascript
使用js实现雪花飘落效果
Aug 26 Javascript
jQuery添加/改变/移除CSS类及判断是否已经存在CSS
Aug 20 Javascript
javascript手风琴下拉菜单实现代码
Nov 12 Javascript
Javascript typeof与instanceof的区别
Oct 18 Javascript
JS仿京东移动端手指拨动切换轮播图效果
Apr 10 Javascript
js实现下一页页码效果
Mar 07 Javascript
Javascript创建类和对象详解
May 31 Javascript
jQuery取得元素标签名称小结(附代码)
Aug 16 jQuery
写给小白看的JavaScript异步
Nov 29 Javascript
node中使用log4js4.x版本记录日志的方法
Aug 20 Javascript
JavaScript中判断为整数的多种方式及保留两位小数的方法
Sep 09 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
PHILIPS L4X25T电路分析和打理
2021/03/02 无线电
模板引擎正则表达式调试小技巧
2011/07/20 PHP
PHP中操作ini配置文件的方法
2013/04/25 PHP
一个严格的PHP Session会话超时时间设置方法
2014/06/10 PHP
php实现给图片加灰色半透明效果的方法
2014/10/20 PHP
php中文验证码实现方法
2015/06/18 PHP
基于ThinkPHP5.0实现图片上传插件
2017/09/25 PHP
Jquery Ajax学习实例4 向WebService发出请求,返回实体对象的异步调用
2010/03/16 Javascript
JS命名空间的另一种实现
2013/08/09 Javascript
javascript从image转换为base64位编码的String
2014/07/29 Javascript
Javascript验证用户输入URL地址是否为空及格式是否正确
2014/10/09 Javascript
JavaScript常用字符串与数组扩展函数小结
2016/04/24 Javascript
基于jQuery实现顶部导航栏功能
2016/12/27 Javascript
Node.js使用cookie保持登录的方法
2018/05/11 Javascript
js实现倒计时秒杀效果
2020/03/25 Javascript
Element Notification通知的实现示例
2020/07/27 Javascript
JS实现手风琴特效
2020/11/08 Javascript
用python实现批量重命名文件的代码
2012/05/25 Python
Python对象转JSON字符串的方法
2016/04/27 Python
Python 多核并行计算的示例代码
2017/11/07 Python
使用Python制作微信跳一跳辅助
2018/01/31 Python
python 异或加密字符串的实例
2018/10/14 Python
pandas数据筛选和csv操作的实现方法
2019/07/02 Python
详解python statistics模块及函数用法
2019/10/27 Python
使用Puppeteer爬取微信文章的实现
2020/02/11 Python
Python的赋值、深拷贝与浅拷贝的区别详解
2020/02/12 Python
Python交互环境下打印和输入函数的实例内容
2020/02/16 Python
Python DES加密实现原理及实例解析
2020/07/17 Python
Python 实现一个计时器
2020/07/28 Python
python3代码输出嵌套式对象实例详解
2020/12/03 Python
利用css3径向渐变做一张优惠券的示例
2018/03/22 HTML / CSS
优秀企业获奖感言
2014/02/01 职场文书
大学生求职工作的自我评价
2014/02/13 职场文书
党校毕业心得体会
2014/09/13 职场文书
2016年校园重阳节广播稿
2015/12/18 职场文书
为什么RedisCluster设计成16384个槽
2021/09/25 Redis