如何通过简单的代码描述Angular父组件、子组件传值


Posted in Javascript onApril 07, 2022

引言

对于稍微接触过Angular组件的同学来说,组件间交互应该没有什么问题。

本文想追求的是用一个通俗解释,帮助自己理解的更准确。

零、知识铺垫

CSS选择器

在介绍父子组件之前,先要了解一个概念——selector、选择器

我们定义一个新组件时,一定会有这个属性:

@Component({
  selector: 'app-village-edit', ①
  templateUrl: './village-edit.component.html',
  styleUrls: ['./village-edit.component.scss']
})

其中①就是选择器,就是告诉别的组件,如果想调用我这个组件,就要使用本组件的选择器<selectorName></selectorName>来调用。

本质上就是定义了组件的HTML标签,就像常见的<p>标签、<button>标签一样。

一、什么是父子组件

就像现实中父母和孩子的关系是相对的一样,一个人对于它的父母来说,就承担了孩子的角色;对于它的孩子来说则承担了父母的角色。

父组件和子组件也是相对的。

假设,一个组件在自己的HTML模板中,通过选择器(也就是特定的HTML标签)来调用其他组件时。我们称这个组件为父组件,而那个被调用的组件称为子组件

二、父组件调用子组件的方法

定义了两个类:

child.component.ts,它的选择器selector是: 'app-child'

parent.component.ts,它的选择器selector是: 'app-parent',

此时,在parent组件的HTMl中引用child组件的选择器:

<app-child></app-child>

这样就完成了子组件的调用。
此时,如果通过路由加载父组件,就会发现子组件也会在特定的位置被渲染出来。

三、父组件向子组件传值

子组件使用@input装饰器接收数据

子组件从父组件接收的值,会保存到子组件的变量中。

所以用来接收传值的变量与普通变量唯一的区别,就是在常规的变量上增加一个@input()注解。

定义普通变量是这样的:

master = 'Master';

如果用来接收传值,只要改成这样:

@Input() master = 'Master';

这样,master变量默认是'Master'字符串。

但如果父组件向其传值,变量就变成了接收的值。

父组件使用方括号[]发送数据

常规方式调用子组件:

<app-child></app-child>

如果子组件可以接收数据,就可以用[propertyName] = value的方法来传值。
例如:

<app-child [master]="hero"> </app-child>

用这种写法可以实现:一旦组件渲染完成后,子组件中的master变量就是'hero'的值了。

当父组件中的变量值变化时,子组件也会同步变化,也就是说,子组件可以监听传过来的值的变化信息

升级:子组件通过set方法监听传入数据变化

在上面的方式中,对于传过来的值,虽然可以监听变化,但局限在于:子组件只能直接使用传入的值。

如果想对传入的值进行处理或过滤,就要稍微调整一下子组件。

常规情况下,子组件是通过给变量加上@Input装饰器来接收参数的:

@Input() name = 'name';

如果想处理参数,只需要把接收传值的变量变成set方法即可:

@Input() 
get name(): string { return this._name; }
set name(name: string) { 
    // 此处可以增加其他处理逻辑
    this._name = name; 
} 
private _name = '';

此时,_name是内部变量,当父组件对于name属性传入值的时候,会自动执行set name方法给_name赋值并增加其他的处理逻辑。

另一种升级:子组件通过ngOnChanges()生命周期钩子监听传入数据变化

官方文档中写到:“当需要监视多个、交互式输入属性的时候,ngOnChanges()比用属性 setter 方法更合适。”

常规情况下,子组件是通过给变量加上@Input装饰器来接收参数的:

@Input() param1 = 'string1';
@Input() param2 = 'string2';

当我们要监听多个变量的变化并做出反应时,可以用ngOnChanges()方法:

@Input() param1 = 'string1';
@Input() param2 = 'string2';

ngOnChanges(changes: SimpleChanges) {  ①

    for (const propName in changes) {  ②
    
        // 通过变量名获取变化信息
        const changedProp = changes[propName];  
        // 获取上一个值
        const from = JSON.stringify(changedProp.previousValue); ③
        // 获取当前值
        const to = JSON.stringify(changedProp.currentValue);     ④
        // 此处可以添加其他处理过程了 ⑤
     } 
     
}

① 执行ngOnChanges()方法时,可以用一个SimpleChanges参数来获得当前组件所有参数的变化情况。

② 通过循环获得每一个参数的上一个值和当前值。

③ 获得上一个值④ 获得当前值⑤ 根据业务逻辑添加其他处理过程

注:由于ngOnChanges方法调用非常频繁,会导致性能问题或者软件崩溃,所以建议少用。

四、子组件向父组件传值

子组件向父组件弹射事件

刚刚讲到了子组件如何获取父组件的传入的变量,如何监听父组件的变化,以及如何处理传入的值。

接下来讲反向的传输:父组件如何监听子组件的变化,并做出反应。

定义普通变量是这样的:

param1 = 'String1';

如果想把这个变量暴露给父组件,需要在变量前加入@output()装饰器,并且给他赋值一个变量弹射器

@Output() param1 = new EventEmitter<string>();

此处EventEmitter是变量弹射器,EventEmitter需要一个确定的类型

但此时,这个param1变量就不能再用等号"="赋值了,如果想让父组件监听到变化,就需要用弹射方法.emit

this.param1.emit("String2");

接下来前往父组件。

父组件监听子组件弹射的事件

刚刚已经在子组件设置好了暴露的变量,那么父组件如何接收呢?

常规的父组件调用子组件:

<app-child></app-child>

如果想监听子组件的某个变量,可以使用圆括号():

<app-child (param1)="function1($event)">

</app-child>

$event 是Angular内置的事件变量。

function1我们在父组件中定义的处理变化的方法。

使用方式如下:

function1(param2: boolean) { 
    // 这个param2为我们自己定义的参数名,
    // 本质上是子组件中变化的param1参数,但不用和子组件中的参数名相同
    // 在此处增加处理过程即可
}

此时,当param1的值发生变化,就会执行function1,并且传入一个事件,事件的实质内容就是子组件定义的param1参数。

function1方法把参数作为param2接收,并添加处理过程。

五、总结

  • Angular中,在HTML通过selector选择器调用的组件称为子组件
  • 父组件向子组件传值使用方括号[]
  • 子组件有两种方式接收值: @input + 变量名、@Input + set方法
  • 子组件想父组件传递事件使用EventEmitter
  • 父组件接收事件使用圆括号(),并声明一个处理方法用来调用

熟悉的风格,一图胜千言:

如何通过简单的代码描述Angular父组件、子组件传值

六、后记

是不是有似曾相识的感觉,在刚开始接触Angular时就知道,可以使用方括号[]来绑定原生HTML标签的某些属性,例如:

<p [id]="sayHelloId" [style.color]="fontColor">
    You can set my color in the component!
</p>

另一方面,还有一个相似之处就是,Angular中也是使用圆括号()来绑定原生HTML标签的某个方法,例如:

<button (click)="onClick()"> 
    点我!
</button>

这些是巧合吗?并不是。

我们可以这样理解:

Angular中所有的原生HTML标签都变成了组件

之所以很多标签中可以用方括号[]绑定属性、使用圆括号()绑定方法,是因为Angular已经为我们扩展了原生的HTML标签,使它们具备了接收和发送数据的能力!

换言之,在Angular内部的组件中,已经为我们加上了许许多多的@input@output装饰器,我们才能方便的绑定这些属性和方法。

总结

到此这篇关于如何通过简单的代码描述Angular父组件、子组件传值的文章就介绍到这了,更多相关Angular父组件、子组件传值内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!


Tags in this post...

Javascript 相关文章推荐
JavaScript 比较时间大小的代码
Apr 24 Javascript
JS操作图片(增,删,改) 例子
Apr 17 Javascript
javascript中的self和this用法小结
Feb 08 Javascript
JS自定义选项卡函数及用法实例分析
Sep 02 Javascript
jQuery中通过ajax调用webservice传递数组参数的问题实例详解
May 20 Javascript
javascript设计模式之策略模式学习笔记
Feb 15 Javascript
大白话讲解JavaScript的Promise
Apr 06 Javascript
Javascript(es2016) import和require用法和区别详解
Aug 11 Javascript
node的process以及child_process模块学习笔记
Mar 06 Javascript
vscode 开发Vue项目的方法步骤
Nov 25 Javascript
vue前后分离调起微信支付
Jul 29 Javascript
vue-router路由模式详解(小结)
Aug 26 Javascript
TypeScript 使用 Tuple Union 声明函数重载
Apr 07 #Javascript
Axios代理配置及封装响应拦截处理方式
vue-cil之axios的二次封装与proxy反向代理使用说明
Apr 07 #Vue.js
动态规划之使用备忘录来改进Javascript函数
Apr 07 #Javascript
vue实现拖拽交换位置
Apr 07 #Vue.js
使用Ajax实现进度条的绘制
Vue.Draggable实现交换位置
You might like
如何取得中文字符串中出现次数最多的子串
2013/08/08 PHP
php之Smarty模板使用方法示例详解
2014/07/08 PHP
Laravel 5框架学习之Laravel入门和新建项目
2015/04/07 PHP
简单介绍PHP的责任链编程模式
2015/08/11 PHP
mysql查找删除重复数据并只保留一条实例详解
2016/09/24 PHP
php使用 readfile() 函数设置文件大小大小的方法
2017/08/11 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
PHP压缩图片功能的介绍
2019/03/21 PHP
php中yii框架实例用法
2020/12/22 PHP
jquery 学习之二 属性(html()与html(val))
2010/11/25 Javascript
javascript 进阶篇2 CSS XML学习
2012/03/14 Javascript
高性能Javascript笔记 数据的存储与访问性能优化
2012/08/02 Javascript
jQuery选择器中含有空格的使用示例及注意事项
2013/08/25 Javascript
带左右箭头图片轮播的JS代码
2013/12/18 Javascript
jQuery的ajax和遍历数组json实例代码
2016/08/01 Javascript
使用Angular缓存父页面数据的方法
2017/01/03 Javascript
利用原生JS与jQuery实现数字线性变化的动画
2017/02/24 Javascript
javascript回调函数的概念理解与用法分析
2017/05/27 Javascript
详解vue跨组件通信的几种方法
2017/06/15 Javascript
Angular2.0/4.0 使用Echarts图表的示例代码
2017/12/07 Javascript
vue 全选与反选的实现方法(无Bug 新手看过来)
2018/02/09 Javascript
js实现鼠标点击飘爱心效果
2020/08/19 Javascript
Linux系统上Nginx+Python的web.py与Django框架环境
2015/12/25 Python
python实现数据写入excel表格
2018/03/25 Python
Python生成任意范围任意精度的随机数方法
2018/04/09 Python
Python-while 计算100以内奇数和的方法
2019/06/11 Python
Python django框架输入汉字,数字,字符生成二维码实现详解
2019/09/24 Python
pytorch中tensor.expand()和tensor.expand_as()函数详解
2019/12/27 Python
python编程进阶之异常处理用法实例分析
2020/02/21 Python
为什么称python为胶水语言
2020/06/16 Python
加拿大约会网站:EliteSingles.ca
2018/01/12 全球购物
Sneaker Studio法国:购买运动鞋
2018/06/08 全球购物
企业演讲稿范文
2013/12/28 职场文书
国际商务专业毕业生自我鉴定2014
2014/09/27 职场文书
销售区域经理岗位职责
2015/04/10 职场文书
SpringBoot工程下使用OpenFeign的坑及解决
2021/07/02 Java/Android