详解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中的Location地址对象
Jan 16 Javascript
jquery 经典动画菜单效果代码
Jan 26 Javascript
ImageZoom 图片放大镜效果(多功能扩展篇)
Apr 14 Javascript
javascript 图片裁剪技巧解读
Nov 15 Javascript
js获取下拉列表框中的value和text的值示例代码
Jan 11 Javascript
jQuery制作拼图小游戏
Jan 12 Javascript
jQuery实现文本框输入同步的方法
Jun 20 Javascript
纯js仿淘宝京东商品放大镜功能
Mar 02 Javascript
angular中使用Socket.io实例代码
Jun 03 Javascript
javascript实现最长公共子序列实例代码
Feb 05 Javascript
vue 解决数组赋值无法渲染在页面的问题
Oct 28 Javascript
JS页面动态绘图工具SVG,Canvas,VML介简介
Oct 16 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
phpmyadmin中配置文件现在需要绝密的短语密码的解决方法
2007/02/11 PHP
php 图片上传类代码
2009/07/17 PHP
获取远程文件大小的php函数
2010/01/11 PHP
php使用$_POST或$_SESSION[]向js函数传参
2014/09/16 PHP
php绘图之在图片上写中文和英文的方法
2015/01/24 PHP
PHP基于phpqrcode生成带LOGO图像的二维码实例
2015/07/10 PHP
form自动提交实例讲解
2017/07/10 PHP
php高性能日志系统 seaslog 的安装与使用方法分析
2020/02/29 PHP
jquery ui dialog里调用datepicker的问题
2009/08/06 Javascript
浅析Node.js中的内存泄漏问题
2015/06/23 Javascript
React学习笔记之条件渲染(一)
2017/07/02 Javascript
jQuery封装animate.css的实例
2018/01/04 jQuery
使用Vue开发一个实时性时间转换指令
2018/01/17 Javascript
Vue-cli中为单独页面设置背景色的实现方法
2018/02/11 Javascript
jQuery无冲突模式详解
2019/01/17 jQuery
vue实现微信获取用户信息的方法
2019/03/21 Javascript
微信小程序实现订单倒计时
2020/11/01 Javascript
JS中的算法与数据结构之栈(Stack)实例详解
2019/08/20 Javascript
p5.js绘制创意自画像
2019/11/04 Javascript
小程序使用分包的示例代码
2020/03/23 Javascript
JavaScript对象字面量和构造函数原理与用法详解
2020/04/18 Javascript
通过实例解析jQ Ajax操作相关原理
2020/09/23 Javascript
Python使用cx_Oracle调用Oracle存储过程的方法示例
2017/10/07 Python
python 实现A*算法的示例代码
2018/08/13 Python
python 有效的括号的实现代码示例
2019/11/11 Python
Python通过VGG16模型实现图像风格转换操作详解
2020/01/16 Python
python实现连连看游戏
2020/02/14 Python
python和php学习哪个更有发展
2020/06/17 Python
python分布式爬虫中消息队列知识点详解
2020/11/26 Python
Python 图片处理库exifread详解
2021/02/25 Python
Aerosoles爱柔仕官网:美国舒软女鞋品牌
2017/07/17 全球购物
软件测试企业面试试卷
2016/07/13 面试题
社区平安建设汇报材料
2014/08/14 职场文书
学习教师敬业奉献模范事迹材料思想汇报
2014/09/19 职场文书
财政局党的群众路线教育实践活动整改方案
2014/09/21 职场文书
2014年护士个人工作总结
2014/11/11 职场文书