详解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 相关文章推荐
SWFObject 2.1以上版本语法介绍
Jul 10 Javascript
基于jQuery的左右滚动实现代码
Dec 03 Javascript
NODE.JS加密模块CRYPTO常用方法介绍
Jun 05 Javascript
控制文字内容的显示与隐藏示例
Jun 11 Javascript
javascript搜索框点击文字消失失焦时文本出现
Sep 18 Javascript
js获取浏览器基本信息大全
Nov 27 Javascript
setTimeout内不支持jquery的选择器的解决方案
Apr 28 Javascript
javascript字符串对象常用api函数小结(连接,替换,分割,转换等)
Sep 20 Javascript
Vue组件间通信 Vuex的用法解析
Aug 05 Javascript
Jquery实现获取子元素的方法分析
Aug 24 jQuery
浅析vue中的provide / inject 有什么用处
Nov 10 Javascript
微信小程序如何实现精确的日期时间选择器
Jan 21 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缓存的详解
2013/05/15 PHP
php判断用户是否手机访问代码
2015/06/08 PHP
Laravel框架使用Seeder实现自动填充数据功能
2018/06/13 PHP
jquery实现漫天雪花飞舞的圣诞祝福雪花效果代码分享
2015/08/20 Javascript
Angular中$compile源码分析
2016/01/28 Javascript
详解Vue自定义过滤器的实现
2017/01/10 Javascript
老生常谈jquery中detach()和remove()的区别
2017/03/02 Javascript
JavaScript数组和对象的复制
2017/03/21 Javascript
JS实现AES加密并与PHP互通的方法分析
2017/04/19 Javascript
详解weex默认webpack.config.js改造
2018/01/08 Javascript
小程序自定义组件实现城市选择功能
2018/07/18 Javascript
webpack之引入图片的实现及问题
2018/10/08 Javascript
深入理解JS异步编程-Promise
2019/06/03 Javascript
python定时执行指定函数的方法
2015/05/27 Python
json跨域调用python的方法详解
2017/01/11 Python
Python基于sklearn库的分类算法简单应用示例
2018/07/09 Python
对python内置map和six.moves.map的区别详解
2018/12/19 Python
详解python 模拟豆瓣登录(豆瓣6.0)
2019/04/18 Python
Python求两点之间的直线距离(2种实现方法)
2019/07/07 Python
python gdal安装与简单使用
2019/08/01 Python
python 中值滤波,椒盐去噪,图片增强实例
2019/12/18 Python
100%法国制造的游戏和玩具:Les Jouets Français
2021/03/02 全球购物
什么是反射
2012/03/17 面试题
个人求职简历中英文自我评价
2013/12/16 职场文书
公司营业员的自我评价
2014/03/04 职场文书
医学生就业推荐表自我鉴定
2014/03/26 职场文书
商场客服专员岗位职责
2014/06/13 职场文书
学校党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
党的群众路线批评与自我批评范文
2014/10/16 职场文书
党员查摆四风问题思想汇报
2014/10/25 职场文书
社区服务活动报告
2015/02/05 职场文书
人与自然观后感
2015/06/16 职场文书
餐厅服务员管理制度
2015/08/05 职场文书
2016国庆节67周年红领巾广播稿
2015/12/18 职场文书
详解Nginx启动失败的几种错误处理
2021/04/01 Servers
Python基础详解之描述符
2021/04/28 Python