react初探(二)之父子组件通信、封装公共组件

一、前言

在组件方面react和Vue一样的,核心思想玩的就是组件,下面举两个组件常用的情景。

场景一:假如我们现在有一个页面包含表格以及多个弹框,这种时候如果将这个页面的业务代码写在一个组件中,那么这一块的代码会看着非常恶心。如果这个时候我们将这个页面的表格以及弹框这些单独的模块分别写成组件的形式,然后再在这个页面中将这些组件引入进来,那样我们的代码会看着非常整洁。这样做会需要使用到父子组件之间的通信,下面会详细解释。

场景二:日常项目中我们会经常遇到某一个功能会在不同地方使用,但是每次使用的时候都会有一些小差别。比如在一个页面中我们有一个地方叫 “上传头像”,在另外一个地方叫 “上传证书” 。这种情况我们封装一个公共的上传图片的组件,但是这个组件在使用的时候在不同的地方展示的文案或者样式不同。react提供一种类似于Vue的插槽(slot)的功能,自定义的组件使用children属性将子元素传递到输出,具体用法下面会详细解释。

二、定义组件

目前有两种常用的方法定义组件:函数式组件、类组件。

(1) 函数式组件:这种组件表示每一个函数就是一个组件,组件具体的内容由return的值决定。这种组件主要用于纯展示性组件,不存在state的操作。

function Name() {
    return (
        <div>我是Name组件</div>
    )
};

优点:结构简单、写法简单。

缺点:不能使用生命周期的钩子函数、不能进行复杂的操作、只能通过函数传参的形式传递props。

(2)类组件:一般一个jsx文件就是一个类组件,该写法为es6的写法(PS:es5也有一种React.createClass组件写法,但是官方现在主推es6这种写法,所以本文不讲es5的这种写法)。使用类组件可以在constructor钩子函数中初始化一个state,相当于Vue中的data,具体关于state的操作可以看我的Reacr初探(一)

class Age extends Component {
    render() {
        return (
            <div>我是Age组件</div>
        )
    }
}

优点:可以进行复杂的操作、具有生命周期钩子函数、拥有state。

缺点:和函数式组件比起来写法要复杂一点。

PS:后面使用的组件均为类组件

三、父组件 => 子组件

这里我们将引入props的概念了,官方描述:

props是React组件的输入内容。 它们是从父组件传递给子组件的数据。

说白了props就是一个对象,是由父子件的属性提供。父组件提供的属性值可以为变量、常量(变量和常量可以用于 父组件 => 子组件)、函数(可以用于 子组件 => 父组件)、react元素(可以用于封装公共组件),在子组件中使用this.props就可以访问到props对象。

父组件中:
<Age num="18"></Age>

子组件中:
render() {
  return (
    <div>我是Age组件,我今年{this.props.num}岁了</div>
  )
}

注意:props为只读的,所以不能修改props的值,如果修改会报错

但是如果传入props的某一个属性的值是一个对象,在子组件中可以改变传入的该对象的属性或者方法是不会报错的。同时父组件的该对象的值也会改变,但是由于不是使用setState改变的状态,所以组件不会重新渲染。好像有点绕口,我们来举个例子看看。

父组件中:

  constructor(props) {
        super(props)
        this.state = {
            userInfo: {
                name: ‘yjj‘,
                age: 18
            }
        }
    }
    render() {
        return (
            <div className="App">
                <Person info={this.state.userInfo}></Person>
                <div onClick={()=> console.log(this.state.userInfo)}>点我打印userinfo对象</div>
            </div>
        );
    }

子组件中:

  render() {
        this.props.info.age = 25
        return (
            <div>
                <div>姓名:{this.props.info.name}</div>
                <div>年龄:{this.props.info.age}</div>
            </div>
        )
    }

父组件中定义了一个userInfo对象,并且将该对象的值作为info属性传入到子组件。子组件中对this.props.info对象的age属性重新赋值,由于子组件的this.props.info对象指向的指针和父组件中的userInfo对象的指针是一样的。所以父组件中的userInfo对象的age属性实际上也是改变了的,等于25。但是在react中state的值需要使用setState()方法修改,所以不会重新渲染对应的组件。

四、子组件 => 父组件

子组件 => 父组件的通信实际上就是通过父组件给子组件传递的属性值为函数,子组件在相应的情况下调用该函数。

父组件中:

  constructor(props) {
        super(props)
        this.state = {
            age: 18
        }
    }
    changeAge = () => {
        this.setState({
            age: 20
        })
    }
    render() {
        return (
            <div className="App">
                <Person changeAgeEvent={this.changeAge}></Person>
                <div>当前年龄:{this.state.age}</div>
            </div>
        );
    }

子组件中:

    render() {return (
            <div>
                <div onClick={() => {this.props.changeAgeEvent()}}>点我改变年龄的值</div>
            </div>
        )
    }

父组件的changeAgeEvent的值为this.changeAge函数,在子组件中使用this.props.changeEvent()调用父组件的函数。

如果要子组件给父组件传参,只需要在调用函数的时候加上需要的参数即可。

父组件中:
changeAge = (age) => {
    this.setState({
        age
    })
}

子组件中:
<div onClick={() => {this.props.changeAge(100)}}>点我改变年龄的值为100</div>  // 子组件给父组件传参

五、封装公共组件

在前言中提到的场景二的问题,我们希望可以像使用普通的div标签一样使用自定义的组件。例如: <UploadImg><h4>上传头像</h4></UploadImg>。如果这样我们就不用考虑封装的UploadImg组件是在 “上传头像” 还是 “上传证书” 的情况下使用UploadImg组件的时候根据使用的场景传入不同的文案即可。例如:上传头像时使用:<UploadImg><h4>上传头像</h4></UploadImg>; 上传证书时使用:<UploadImg><h4>上传证书</h4></UploadImg>。

在子组件中使用this.props.children就可以获取父组件通过<UploadImg><h4>上传头像</h4></UploadImg>传递过来的 “<h4>上传头像</h4>” 。

父组件中:
<UploadImg><h4>上传头像</h4>/UploadImg>

子组件中:
<div>父组件传递过来的:{this.props.children}</div>

使用this.props.children时,父组件只有一个入口。有的时候使用父组件时有的时候我们需要有多个入口,这种情况我们就需要约定自己的属性而不是使用children。实际上children也是表示是父组件中的一个属性,父组件的属性值不仅限于常量、变量、函数,还可以为react元素。

父组件中:
<UploadImg btnText={<h4>上传头像</h4>} btnNum={<p>1</p>}></UploadImg>

子组件中:
<div>
    <div>父组件传递过来的btnText:{this.props.btnText}</div>
    <div>父组件传递过来的btnNum:{this.props.btnNum}</div>
</div>

父组件中的 btnText属性和btnNum属性的值都是为react元素,在子组件中使用this.props.btnText和this.props.btnNum就可以取得对应的react元素。

六、总结

写了一些demo发现,一个项目说白了就是一个根组件组成,但是这个根组件又由很多子组件组成,这些子组件又是由这些子组件的子组件组成。就这样层层嵌套下去,最终形成的就是一个完整的项目。目前react初探差不多就到此为止,更多深入的知识需要后面在实际项目中使用react后再来总结。

原文地址:https://www.cnblogs.com/heavenYJJ/p/9215021.html

时间: 2024-08-07 11:33:33

react初探(二)之父子组件通信、封装公共组件的相关文章

小程序开发 组件定义(封装)、组件调用、父子组件方法调用、父子组件传值通讯

在小程序开发中,为了提高代码效率,和代码使用率,我们也用到了组件封装, 今天我介绍下如何在小程序中封装一个头部公用组件 首先,所有父组件(调用页面)的json文件都要引用子组件:index.json { "usingComponents": { "header": "../../component/header/header", } } 一,组件定义(封装) 子组件:header.wxml <view name='header' class

Vue子组件向父组件通信,父组件向子组件通信

首先,子组件代码如下 <template> <div style="border:1px solid black;width:400px;"> <h3>我是子组件里的</h3> <button>点击按钮子组件传递父组件</button> <div>我是父组件传子组件显示的:我还没有值</div> </div> </template> <script> ex

vue2.0父子组件通信以及同级组件通信

1.父向子通信 父组件为singer.vue.子组件为list-view.vue.需要把歌手的数据传给子组件.则绑定 :data = 'singers' ,singers为父组件的值.data为子组件接收值的名称 子组件采用props的方式接收.data 里面就是父组件传过来的的值了. 值得注意的是.当定义子组件的值有参数时,props里面的default需要向data函数一样写 2 子组件向父组件派发事件 (1)子组件做了一个点击事件 selectItem(item),并传递了一个值 (2)m

Vuejs——(10)组件——父子组件通信

版权声明:出处http://blog.csdn.net/qq20004604 目录(?)[+] 本篇资料来于官方文档: http://cn.vuejs.org/guide/components.html#u7236_u5B50_u7EC4_u4EF6_u901A_u4FE1 本文是在官方文档的基础上,更加细致的说明,代码更多更全. 简单来说,更适合新手阅读 (二十七)父子组件通信 ①访问子组件.父组件.根组件: this.$parent    访问父组件 this.$children   访问子

React组件通信的几种方式

需要组件之进行通信的几种情况? 父组件向子组件通信?? 子组件向父组件通信?? 跨级组件通信?? 没有嵌套关系组件之间的通信? 1. 父组件向子组件通信React数据流动是单向的,父组件向子组件通信也是最常见的;父组件通过props向子组件传递需要的信息?Child.jsximport?React?from?'react';import?PropTypes?from?'prop-types';export?default?function?Child({?name?})?{????return?

react native组件通信

在日常开发过程中,组件之间的通信我们应该经常用到,也是我们开发过程中不可或缺的一部分.组件可以分为父子组件以及兄弟组件,下面就不同组件之间的通信进行说明. 父组件通过props与子组件通信 定义父组件 import React, {Component} from 'react'; import { Text, StyleSheet, View, TouchableOpacity } from 'react-native'; import Child from "./Child"; ex

React:快速上手(2)——组件通信

React:快速上手(2)--组件通信 向父组件传递数据 父组件可以通过设置子组件的props属性进行向子组件传值,同时也可以传递一个回调函数,来获取到子组件内部的数据. 效果演示 子组件是输入框,父组件及时获取到输入框内容然后更新右边标签. 父组件传递回调函数 父组件传递一个方法,即updateSpan,用于更新span内容. class Father extends React.Component{ constructor(props){ super(props) this.state =

vue组件通信的几种方式

最近用vue开发项目,记录一下vue组件间通信几种方式 第一种,父子组件通信 一.父组件向子组件传值 1.创建子组件,在src/components/文件夹下新建一个Child.vue 2.Child.vue的中创建props,然后创建一个名为message的属性 child.png 3.在App.vue中注册Child组件,并在template中加入child标签,标签中添加message属性并赋值 App2.png 4.保存修改的文件,查看浏览器 browser.png 5.我们依然可以对m

vue组件详解(三)——组件通信

组件之间通信可以用下图表示: 组件关系可分为父子组件通信.兄弟组件通信.跨级组件通信. 一.自定义事件 当子组件需要向父组件传递数据时,就要用到自定义事件. 子组件用$emit ()来触发事件,父组件用$on()来监昕子组件的事件. 父组件可以直接在子组件的自定义标签上使用v-on 来监昕子组件触发的自定义事件,如: <div id="app9"> <p>总数:{{total}}</p> <my-component9 @add="ge