如何通过简单的代码描述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 相关文章推荐
跨域传值即主页面与iframe之间互相传值
Dec 09 Javascript
jQuery中$.extend()用法实例
Jun 24 Javascript
jQuery实现可展开折叠的导航效果示例
Sep 12 Javascript
浅谈js内置对象Math的属性和方法(推荐)
Sep 19 Javascript
浅谈JS中的!=、== 、!==、===的用法和区别
Sep 24 Javascript
js实现表单提交后不重新刷新当前页面
Nov 30 Javascript
深入理解Webpack 中路径的配置
Jun 17 Javascript
Vue 自定义动态组件实例详解
Mar 28 Javascript
Element输入框带历史查询记录的实现示例
Jan 15 Javascript
微信小程序拼接图片链接无底洞深入探究
Sep 03 Javascript
JavaScript图片旋转效果实现方法详解
Jun 28 Javascript
React实现阿里云OSS上传文件的示例
Aug 10 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+MySQL5.0中文乱码解决方法
2006/11/20 PHP
php生成SessionID和图片校验码的思路和实现代码
2009/03/10 PHP
JSON在PHP中的应用介绍
2012/09/08 PHP
简述php环境搭建与配置
2016/12/05 PHP
Javascript调试工具(下载)
2007/01/09 Javascript
基于Jquery+Ajax+Json的高效分页实现代码
2011/10/29 Javascript
js控制的回到页面顶端goTop的代码实现
2013/03/20 Javascript
解析jQuery与其它js(Prototype)库兼容共存
2013/07/04 Javascript
可选择和输入的下拉列表框示例
2013/11/05 Javascript
表单提交前触发函数返回true表单才会提交
2014/03/11 Javascript
javascript制作的网页侧边弹出框思路及实现代码
2014/05/21 Javascript
javascript实现瀑布流自适应遇到的问题及解决方案
2015/01/28 Javascript
JS取模、取商及取整运算方法示例
2016/10/13 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的方法
2016/11/29 Javascript
JS基于递归算法实现1,2,3,4,5,6,7,8,9倒序放入数组中的方法
2017/01/03 Javascript
vue better-scroll插件使用详解
2018/01/25 Javascript
vue2.0+vuex+localStorage代办事项应用实现详解
2018/05/31 Javascript
JS引用传递与值传递的区别与用法分析
2018/06/01 Javascript
vue实现浏览器全屏展示功能
2019/11/27 Javascript
Vue-cli3生成的Vue项目加载Mxgraph方法示例
2020/05/31 Javascript
小程序中手机号识别的示例
2020/12/14 Javascript
vue3.0 项目搭建和使用流程
2021/03/04 Vue.js
[03:03]2014DOTA2西雅图国际邀请赛 Alliance战队巡礼
2014/07/07 DOTA
[20:30]职业巡回赛回顾
2018/08/09 DOTA
[01:04:14]OG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[01:02:26]DOTA2-DPC中国联赛 正赛 SAG vs RNG BO3 第二场 1月18日
2021/03/11 DOTA
Python __setattr__、 __getattr__、 __delattr__、__call__用法示例
2015/03/06 Python
Python实现的使用telnet登陆聊天室实例
2015/06/17 Python
flask框架配置mysql数据库操作详解
2019/11/29 Python
浅谈python量化 双均线策略(金叉死叉)
2020/06/03 Python
俄罗斯宠物用品网上商店:ZooMag
2019/12/12 全球购物
局部内部类是否可以访问非final变量?
2013/04/20 面试题
为什么要有struct关键字
2012/05/08 面试题
作弊检讨书1000字
2014/02/01 职场文书
五年级作文之想象作文
2019/10/30 职场文书
windows10声卡驱动怎么安装?win10声卡驱动安装操作步骤教程
2022/08/05 数码科技