详解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模拟实现Array的sort方法
Dec 11 Javascript
jQuery入门第一课 jQuery选择符
Mar 14 Javascript
js 优化次数过多的循环 考虑到性能问题
Mar 05 Javascript
jquery利用event.which方法获取键盘输入值的代码
Oct 09 Javascript
JS实现将人民币金额转换为大写的示例代码
Feb 13 Javascript
轻量级网页遮罩层jQuery插件用法实例
Jul 31 Javascript
JavaScript中Date对象的常用方法示例
Oct 24 Javascript
javascript表单处理具体实现代码(表单、链接、按钮)
May 07 Javascript
jQuery事件用法详解
Oct 06 Javascript
js实现一个猜数字游戏
Mar 31 Javascript
JavaScript 中Date对象的格式化代码方法汇总
Sep 06 Javascript
JavaScript实现封闭区域布尔运算的示例代码
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 表单提交给自己
2008/07/24 PHP
PHP中的array数组类型分析说明
2010/07/27 PHP
paypal即时到账php实现代码
2010/11/28 PHP
php echo, print, print_r, sprintf, var_dump, var_expor的使用区别
2013/06/20 PHP
PHP下使用mysqli的函数连接mysql出现warning: mysqli::real_connect(): (hy000/1040): ...
2016/02/14 PHP
自定义min版smarty模板引擎MinSmarty.class.php文件及用法
2016/05/20 PHP
php自定义函数实现JS的escape的方法示例
2016/07/07 PHP
页面使用密码保护代码
2013/04/10 Javascript
js实现的切换面板实例代码
2013/06/17 Javascript
js实现接收表单的值并将值拼在表单action后面的方法
2015/11/23 Javascript
浅述节点的创建及常见功能的实现
2016/12/15 Javascript
微信小程序 flex实现导航实例详解
2017/04/26 Javascript
js 用于检测类数组对象的函数方法
2017/05/02 Javascript
深入理解angular2启动项目步骤
2017/07/15 Javascript
解决Vue 浏览器后退无法触发beforeRouteLeave的问题
2017/12/24 Javascript
webpack里使用jquery.mCustomScrollbar插件的方法
2018/05/30 jQuery
如何使用puppet替换文件中的string
2018/12/06 Javascript
ios中视频的最后一桢问题解决
2019/05/14 Javascript
python实现雨滴下落到地面效果
2018/06/21 Python
python 实现查找文件并输出满足某一条件的数据项方法
2019/06/12 Python
分享PyCharm的几个使用技巧
2019/11/10 Python
Python 脚本实现淘宝准点秒杀功能
2019/11/13 Python
浅析python内置模块collections
2019/11/15 Python
python 如何去除字符串头尾的多余符号
2019/11/19 Python
Python定义函数实现累计求和操作
2020/05/03 Python
关于h5中的fetch方法解读(小结)
2017/11/15 HTML / CSS
美国家庭鞋店:Shoe Sensation
2019/09/27 全球购物
PyQt 如何创建自定义QWidget
2021/03/24 Python
公司前台接待岗位职责
2013/12/03 职场文书
建筑工程毕业生自我鉴定
2014/01/14 职场文书
机电专业大学生职业规划书范文
2014/02/25 职场文书
事务机电主管工作职责
2014/02/25 职场文书
幼儿园感谢信
2015/01/21 职场文书
社区六一儿童节活动总结
2015/02/11 职场文书
天鹅湖观后感
2015/06/09 职场文书
python爬虫之selenium库的安装及使用教程
2021/05/23 Python