详解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 数组的 uniq 方法
Jan 23 Javascript
当鼠标滑过文本框自动选中输入框内容的JS代码分享
Nov 26 Javascript
indexOf 和 lastIndexOf 使用示例介绍
Sep 02 Javascript
javascript在当前窗口关闭前检测窗口是否关闭
Sep 29 Javascript
使用jquery实现鼠标滑过弹出更多相关信息层附源码下载
Nov 23 Javascript
JS实现旋转木马式图片轮播效果
Jan 18 Javascript
Bootstrap中data-target 到底是什么
Feb 14 Javascript
深入解析Vue 组件命名那些事
Jul 18 Javascript
react-router 路由切换动画的实现示例
Dec 03 Javascript
Vue2.0使用嵌套路由实现页面内容切换/公用一级菜单控制页面内容切换(推荐)
May 08 Javascript
JS实现4位随机验证码
Oct 19 Javascript
vue实现列表垂直无缝滚动
Apr 08 Vue.js
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
删除html标签得到纯文本可处理嵌套的标签
2014/04/28 PHP
PHP加密解密类实例分析
2015/04/20 PHP
php使用str_shuffle()函数生成随机字符串的方法分析
2017/02/17 PHP
javascript String 的扩展方法集合
2008/06/01 Javascript
在html页面中包含共享页面的方法
2008/10/24 Javascript
仿校内登陆框,精美,给那些很厉害但是没有设计天才的程序员
2008/11/24 Javascript
jquery图片上下tab切换效果
2011/03/18 Javascript
基于jquery的15款幻灯片插件
2011/04/10 Javascript
jQuery :nth-child前有无空格的区别分析
2011/07/11 Javascript
jquery中的mouseleave和mouseout的区别 模仿下拉框效果
2012/02/07 Javascript
JS实现字体选色板实例代码
2013/11/20 Javascript
easyui datagrid 键盘上下控制选中行示例
2014/03/31 Javascript
JQuery插件iScroll实现下拉刷新,滚动翻页特效
2014/06/22 Javascript
nodejs事件的监听与触发的理解分析
2015/02/12 NodeJs
JS实现点击文字对应DIV层不停闪动效果的方法
2015/03/02 Javascript
JavaScript 性能优化小结
2015/10/12 Javascript
js验证身份证号有效性并提示对应信息
2015/10/19 Javascript
信息页文内画中画广告js实现代码(文中加载广告方式)
2016/01/03 Javascript
Javascript 两种刷新方法以及区别和适用范围
2017/01/17 Javascript
详解AngularJS1.6版本中ui-router路由中/#!/的解决方法
2017/05/22 Javascript
vue引入ueditor及node后台配置详解
2018/01/03 Javascript
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
2018/05/01 Javascript
vue父子组件的通信方法(实例详解)
2019/11/10 Javascript
ES6使用新特性Proxy实现的数据绑定功能实例
2020/05/11 Javascript
Vue使用预渲染代替SSR的方法
2020/07/02 Javascript
javascript实现点击小图显示大图
2020/11/29 Javascript
SublimeText 2编译python出错的解决方法(The system cannot find the file specified)
2013/11/27 Python
python 爬虫基本使用——统计杭电oj题目正确率并排序
2020/10/26 Python
你不知道的葡萄干处理法、橙蜜处理法、二氧化碳酵母法
2021/03/17 冲泡冲煮
纽约香氛品牌:NEST Fragrance
2018/10/15 全球购物
能否解释一下XSS cookie盗窃是什么意思
2012/06/02 面试题
前台文员个人求职信范文
2014/01/05 职场文书
简历中的自我评价怎么写
2014/01/29 职场文书
名人传读书笔记
2015/06/26 职场文书
基督教追悼会答谢词
2015/09/29 职场文书
小学生作文写作技巧100例,非常实用!
2019/07/08 职场文书