详解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 使用点滴函数代码
May 20 Javascript
js Html结构转字符串形式显示代码
Nov 15 Javascript
Js-$.extend扩展方法使方法参数更灵活
Jan 15 Javascript
可简单避免的三个JS发布错误的详细介绍
Aug 02 Javascript
JQuery中使用Ajax赋值给全局变量异常的解决方法
Jan 10 Javascript
js+html5实现canvas绘制镂空字体文本的方法
Jun 05 Javascript
jQuery.prop() 使用详解
Jul 19 Javascript
jquery中validate与form插件提交的方式小结
Mar 26 Javascript
JS传递对象数组为参数给后端,后端获取的实例代码
Jun 28 Javascript
微信小程序 条件渲染详解
Oct 09 Javascript
webpack的 rquire.context用法实现工程自动化的方法
Feb 07 Javascript
使用jQuery实现购物车
Oct 29 jQuery
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
德生PL450的电路分析和低放电路的改进办法
2021/03/02 无线电
php 执行系统命令的方法
2009/07/07 PHP
PHP面向对象的进阶学习(抽像类、接口、final、类常量)
2012/05/07 PHP
php页码形式分页函数支持静态化地址及ajax分页
2014/03/28 PHP
PHP附件下载中文名称乱码的解决方法
2015/12/17 PHP
初学JavaScript第二章
2008/09/30 Javascript
12款经典的白富美型—jquery图片轮播插件—前端开发必备
2013/01/08 Javascript
我的Node.js学习之路(四)--单元测试
2014/07/06 Javascript
AngularJS实现元素显示和隐藏的几个案例
2015/12/09 Javascript
js和jQuery设置Opacity半透明 兼容IE6
2016/05/24 Javascript
vue动态设置路由权限的主要思路
2021/01/13 Vue.js
[44:15]DOTA2上海特级锦标赛主赛事日 - 5 败者组决赛Liquid VS EG第二局
2016/03/06 DOTA
Python实现过滤单个Android程序日志脚本分享
2015/01/16 Python
在树莓派2或树莓派B+上安装Python和OpenCV的教程
2015/03/30 Python
Python isinstance函数介绍
2015/04/14 Python
在Django的视图中使用数据库查询的方法
2015/07/16 Python
使用Python脚本生成随机IP的简单方法
2015/07/30 Python
Python实现识别手写数字大纲
2018/01/29 Python
Python3内置模块pprint让打印比print更美观详解
2019/06/02 Python
python线程中的同步问题及解决方法
2019/08/29 Python
使用keras实现densenet和Xception的模型融合
2020/05/23 Python
python如何设置静态变量
2020/09/07 Python
CSS3只让背景图片旋转180度的实现示例
2021/03/09 HTML / CSS
突袭HTML5之Javascript API扩展1—Web Worker异步执行及相关概述
2013/01/31 HTML / CSS
中国综合性网上购物商城:当当(网上卖书起家)
2016/11/16 全球购物
印度最好的在线药品订购网站:PharmEasy
2018/11/30 全球购物
法雷奥SQA(electric)面试问题
2016/01/23 面试题
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢?
2016/08/18 面试题
班组长的岗位职责
2013/12/09 职场文书
中国文明网向国旗敬礼活动精彩寄语2014
2014/09/27 职场文书
2014年社区工作总结
2014/11/18 职场文书
逃课检讨书怎么写
2015/01/01 职场文书
人事局接收函
2015/01/31 职场文书
文化大革命观后感
2015/06/17 职场文书
MySQL系列之十二 备份与恢复
2021/07/02 MySQL
Java面试题冲刺第十八天--Spring框架3
2021/08/07 面试题