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

目录
  • 引言
  • 零、知识铺垫
    • CSS选择器
  • 一、什么是父子组件
  • 二、父组件调用子组件的方法
  • 三、父组件向子组件传值
    • 子组件使用@input装饰器接收数据
    • 父组件使用方括号[]发送数据
    • 升级:子组件通过set方法监听传入数据变化
    • 另一种升级:子组件通过ngOnChanges()生命周期钩子监听传入数据变化
  • 四、子组件向父组件传值
    • 子组件向父组件弹射事件
    • 父组件监听子组件弹射的事件
  • 五、总结
  • 六、后记
  • 总结

引言

对于稍微接触过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时就知道,可以使用方括号[]来绑定原生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父组件、子组件传值内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Angular5.0 子组件通过service传递值给父组件的方法

    一.引言 我们使用ngx-loading,需要在app.component.html上写模板,绑定一个布尔值loading.此时如果我们想在其他组件中使用这个loading控件,就需要在每个组件的html重新写模板,这就显得累赘了.在此,我们以ngx-loading为例,展示子组件如何通过service改变app组件中的布尔值loading. // app.component.html <ngx-loading [show]="loading" [config]="{

  • Angular父组件调用子组件的方法

    理解组件 组件是一种特殊的指令,使用更简单的配置项来构建基于组件的应用程序架构 这样他能简单地写app,通过类似的web Component 或者angular2的样式. web Component 是一个规范.马上就要成为标准. 应用组件的优点: 比普通指令配置还简单 提供更好的默认设置和最好的实践 对基于组建的应用架构更优化. 对angular2的升级更平滑. 不用组建的情况: 对那些在 compile或者pre-link阶段要执行操作的指令,组件不能用,因为无法到达那个阶段. 如果你想定义

  • angular5 子组件监听父组件传入值的变化方法

    项目中遇到一个问题,就是在ngInit()中调用方法,只调用一次的问题,当父组件传值变化时,并不会再次执行. import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; import { NavController } from 'ionic-angular'; @Component({ selector: 'cs-img-lazy', templateUrl: 'cs-img-lazy.html' })

  • angular6.0使用教程之父组件通过url传递id给子组件的方法

    在angular6.0使用教程:angular主从组件章节我们介绍了父组件向子组件传递数据,当时是在同一个页面传递数据的.而本章的angular数据传递将是在不同页面间的传递,即list组件页面向post组件页面传递数据. 第一步:配置post组件的路由: 在上一章angular6.0使用教程:angular6.0的路由使用中我们为angular6.0项目设置了路由,我们只设置了home组件和list组件的路由.我们还要设置post组件的路由,因为post是产品组件,而不同的产品会有不同的id,

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

    目录 引言 零.知识铺垫 CSS选择器 一.什么是父子组件 二.父组件调用子组件的方法 三.父组件向子组件传值 子组件使用@input装饰器接收数据 父组件使用方括号[]发送数据 升级:子组件通过set方法监听传入数据变化 另一种升级:子组件通过ngOnChanges()生命周期钩子监听传入数据变化 四.子组件向父组件传值 子组件向父组件弹射事件 父组件监听子组件弹射的事件 五.总结 六.后记 总结 引言 对于稍微接触过Angular组件的同学来说,组件间交互应该没有什么问题. 本文想追求的是用

  • vue.js 父向子组件传参的实例代码

    1.新建componentA.vue组件,代码如下: store.js代码如下: const STORAGE_KEY = 'todos-vue.js' export default{ fetch(){ return JSON.parse(window.localStorage.getItem(STORAGE_KEY) || '[]') }, save(items){ window.localStorage.setItem(STORAGE_KEY,JSON.stringify(items)); }

  • vue.js  父向子组件传参的实例代码

    1.新建componentA.vue组件,代码如下: store.js代码如下: const STORAGE_KEY = 'todos-vue.js' export default{ fetch(){ return JSON.parse(window.localStorage.getItem(STORAGE_KEY) || '[]') }, save(items){ window.localStorage.setItem(STORAGE_KEY,JSON.stringify(items)); }

  • Vue.js父与子组件之间传参示例

    例子:App.vue为父,引入componetA组件之后,则可以在template中使用标签(注意驼峰写法要改成componet-a写法,因为html对大小写不敏感,componenta与componentA对于它来说是一样的,不好区分,所以使用小写-小写这种写法).而子组件componetA中,声明props参数'msgfromfa'之后,就可以收到父向子组件传的参数了.例子中将msgfromfa显示在<p>标签中. App.vue中 <component-a msgfromfa=&q

  • vue elementui 实现搜索栏子组件封装的示例代码

    目录 前言 需求 实现 子组件(search.vue) 父组件部分主要代码(index.vue) 前言 描述: 在基本项目中搜索栏.分页组件格式样式几乎是固定的,只是对应的数据不同,由于模块会随着需求的不断增加,可能会导致重复代码越来越多,这时可以用到子组件,需要将相同的模块代码统一封装,提高开发效率和页面统一.(自己的想法,只根据自己需求来说) 需求 实现 子组件(search.vue) html <template> <div class="search-main"

  • 详解Angular中实现自定义组件的双向绑定的两种方法

    在 Angular 中,对于表单元素,通过 [(ngModel)] 即可以简单地实现双向绑定.对于自定义组件而言,希望实现同样的效果可以怎么做呢? 1 实现自定义组件的 ngModel 指令 如果希望自定义组件能够具有与表单元素相同的 ngModel 效果,可以通过在组件内实现 ControlValueAccessor 接口达到目的. 对于 [(ngModel)] ,需要至少实现该接口的如下方法: interface ControlValueAccessor { writeValue(obj:

  • vue父组件给子组件的组件传值provide inject的方法

    一般情况下我们父子之间的传值用的是props,这个就不多说了,但是如果想让父给子组件的组件传值怎么办呢,这里我们就可以用到 provide 和 inject(依赖注入) provide/inject需要一起使用,我们可以从父组件的provide传值,子组件或者孙组件,就可以用inject来接受子组件的provide属性值 具体的可以看官网介绍provide/inject:https://cn.vuejs.org/v2/api/#provide-inject 下面我们可以写个简单的例子来演示一下

  • Vue组件通信方式(父传子、子传父、兄弟通信)

    目录 父组件传到子组件 子组件向父组件传值 非父子传参 (事件总线) vue 跨页面双向通信 同源通信 非同源通讯 父组件传到子组件 父组件是通过props属性给子组件通信的 数据是单向流动 父—>子 (子组件中修改props数据,是无效的,会有一个红色警告) 1. 父组件parent.vue代码如下:  <template>    <div class="parent">      <h2>{{ msg }}</h2>      

  • React Hook父组件如何获取子组件的数据/函数

    目录 React Hook父组件获取子组件数据/函数 子组件MyWorldMap 父组件MyTrip React Hook父组件提交子组件form 父组件 子组件 React Hook父组件获取子组件数据/函数 我们知道在react中,常用props实现子组件数据到父组件的传递,但是父组件调用子组件的功能却不常用. 文档上说ref其实不是最佳的选择,但是想着偷懒不学redux,在网上找了很多教程,要不就是hook的讲的太少,要不就是父子组件傻傻分不清,于是只好再啃了一下文档,就学了一下其它hoo

  • Vue父子组件数据双向绑定(父传子、子传父)及ref、$refs、is、:is的使用与区别

    既然有父传子那么肯定有子传父,有子传父肯定也有两者之间相互绑定 这里我们先看一下子传父的写法: 一.子传父:$emit() 看代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>子传父</title> <script src="https://cdn.jsdelivr.net/npm/vue"></sc

随机推荐