如何通过简单的代码描述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中关于执行环境的杂谈
Aug 14 Javascript
contains和compareDocumentPosition 方法来确定是否HTML节点间的关系
Sep 13 Javascript
js如何判断不同系统的浏览器类型
Oct 28 Javascript
js调试工具console.log()方法查看js代码的执行情况
Aug 08 Javascript
AngularJS学习笔记之TodoMVC的分析
Feb 22 Javascript
jQuery实现简洁的导航菜单效果
Nov 23 Javascript
使用vue.js制作分页组件
Jun 27 Javascript
第一次接触神奇的Bootstrap导航条
Aug 09 Javascript
vuex中使用对象展开运算符的示例
Sep 25 Javascript
vue--点击当前增加class,其他删除class的方法
Sep 15 Javascript
JS组件库AlloyTouch实现图片轮播过程解析
May 29 Javascript
openlayers实现地图弹窗
Sep 25 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
PHP获取音频文件的相关信息
2015/06/22 PHP
php注册登录系统简化版
2020/12/28 PHP
phpMyAdmin通过密码漏洞留后门文件
2018/11/20 PHP
javascript 面向对象的JavaScript类
2010/05/04 Javascript
在jQuery 1.5中使用deferred对象的代码(翻译)
2011/03/10 Javascript
jquery实现弹出层遮罩效果的简单实例
2014/03/03 Javascript
Javascript冒泡排序算法详解
2014/12/03 Javascript
nodejs实现获取某宝商品分类
2015/05/28 NodeJs
jQuery判断多个input file 都不能为空的例子
2015/06/23 Javascript
CSS javascript 结合实现悬浮固定菜单效果
2015/08/23 Javascript
基于jQuery Bar Indicator 插件实现进度条展示效果
2015/09/30 Javascript
基于jQuery实现点击列表加载更多效果
2016/05/31 Javascript
jQuery编写网页版2048小游戏
2017/01/06 Javascript
JS高仿抛物线加入购物车特效实现代码
2017/02/20 Javascript
基于javaScript的this指向总结
2017/07/22 Javascript
原生javascript实现的全屏滚动功能示例
2017/09/19 Javascript
Puppeteer 爬取动态生成的网页实战
2018/11/14 Javascript
[06:33]DOTA2亚洲邀请赛小组赛第二日 TOP10精彩集锦
2015/01/31 DOTA
Python使用sorted排序的方法小结
2017/07/28 Python
Python使用回溯法子集树模板获取最长公共子序列(LCS)的方法
2017/09/08 Python
使用apidocJs快速生成在线文档的实例讲解
2018/02/07 Python
python3+selenium实现qq邮箱登陆并发送邮件功能
2019/01/23 Python
Python序列对象与String类型内置方法详解
2019/10/22 Python
Python+OpenCV实现实时眼动追踪的示例代码
2019/11/11 Python
Python包,__init__.py功能与用法分析
2020/01/07 Python
Python通过getattr函数获取对象的属性值
2020/10/16 Python
法学专业应届生求职信
2013/10/16 职场文书
北大自主招生自荐信
2013/10/19 职场文书
体育老师的教学自我评价分享
2013/11/19 职场文书
如何写一封打动人心的求职信
2014/02/17 职场文书
村党支部公开承诺书
2014/05/29 职场文书
销售人员求职信
2014/07/22 职场文书
2015年度物流工作总结
2015/04/30 职场文书
运动会开幕式通讯稿
2015/07/18 职场文书
运动会通讯稿600字
2015/07/20 职场文书
使用Navicat Premium工具将oracle数据库迁移到MySQL
2021/05/27 Oracle