详解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计算页面刷新的次数
Jul 20 Javascript
javascript call方法使用说明
Jan 11 Javascript
滚动图片效果 jquery实现回旋滚动效果
Jan 08 Javascript
jquery写个checkbox——类似邮箱全选功能
Mar 19 Javascript
jQuery使用一个按钮控制图片的伸缩实现思路
Apr 19 Javascript
JQuery导航菜单选择特效
Apr 11 Javascript
BootStrap智能表单demo示例详解
Jun 13 Javascript
将jquery.qqFace.js表情转换成微信的字符码
Dec 01 jQuery
vue 注册组件的使用详解
May 05 Javascript
jQuery实现checkbox全选、反选及删除等操作的方法详解
Aug 02 jQuery
VUE 组件转换为微信小程序组件的方法
Nov 06 Javascript
vue 虚拟DOM的原理
Oct 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
Sony CFR 320 修复改造
2020/03/14 无线电
PHP下打开phpMyAdmin出现403错误的问题解决方法
2013/05/23 PHP
Codeigniter实现智能裁剪图片的方法
2014/06/12 PHP
prototype.js的Ajax对象
2006/09/23 Javascript
Javascript(AJAX)解析XML的代码(兼容FIREFOX/IE)
2010/07/11 Javascript
js 中{},[]中括号,大括号使用详解
2011/05/12 Javascript
JS刷新当前页面的几种方法总结
2013/12/24 Javascript
JQuery EasyUI 日期控件如何控制日期选择区间
2014/05/05 Javascript
初识Javascript小结
2015/07/16 Javascript
js+css实现回到顶部按钮(back to top)
2016/03/02 Javascript
vue编译打包本地查看index文件的方法
2018/02/23 Javascript
Vue2.0 v-for filter列表过滤功能的实现
2018/09/07 Javascript
浅析js中mvvm模式实现的原理
2018/10/06 Javascript
vue中使用vue-pdf的方法详解
2020/09/05 Javascript
Python入门教程之运算符与控制流
2016/08/17 Python
Python类属性的延迟计算
2016/10/22 Python
python获取中文字符串长度的方法
2018/11/14 Python
对Python3.x版本print函数左右对齐详解
2018/12/22 Python
对python过滤器和lambda函数的用法详解
2019/01/21 Python
详解Python静态网页爬取获取高清壁纸
2019/04/23 Python
Django网络框架之HelloDjango项目创建教程
2019/06/06 Python
pyqt5 获取显示器的分辨率的方法
2019/06/18 Python
Pyqt5实现英文学习词典
2019/06/24 Python
Python变量访问权限控制详解
2019/06/29 Python
python创建学生管理系统
2019/11/22 Python
Python实现直播推流效果
2019/11/26 Python
CSS3美化表单控件全集
2016/06/29 HTML / CSS
惠普加拿大在线商店:HP加拿大
2017/09/15 全球购物
中英双版中文教师求职信
2013/10/27 职场文书
毕业生自荐书
2014/02/02 职场文书
服装采购员岗位职责
2014/03/15 职场文书
事业单位分类改革实施方案
2014/03/21 职场文书
关于晚自习早退的检讨书
2014/09/13 职场文书
大学生简历自我评价2015
2015/03/03 职场文书
2015年消防工作总结
2015/04/24 职场文书
关于拾金不昧的感谢信(五篇)
2019/10/18 职场文书