资讯专栏INFORMATION COLUMN

React系列---React(二)组件的prop和state

Labradors / 579人阅读

摘要:给赋值也是构造函数的工作之一。在的构造函数中,还给两个成员函数绑定了当前的执行环境,因为方式创建的组件并不自动给我们绑定到当前实例对象。我们可以利用的功能,避免判断逻辑这种充斥在构造函数之中,让代码更优。

React系列---React(一)初识React
React系列---React(二)组件的prop和state
React系列---React(三)组件的生命周期

组件是React的基石,所有的React应用程序都是基于组件的。基于组件的应用开发是广泛使用的软件开发模式,用分而治之的方法,把一个大的应用分解成若干小的组件,每个组件只关注某个特定功能,但是把组件组合起来,就能构成一个功能庞大的应用。

React组件的数据分为两种,prop和state,无论prop或者state的改变,都可能引发组件的重新渲染。prop是组件对外接口,state是组件内部状态。

第一个组件

用create-react-app工具,初始化一个React项目:

npm create-react-app react-component-demo

创建一个可以计算点击数的组件:
/src/ClickCounter.js:

import React from "react";

class ClickCounter extends React.Component {
    constructor(props) {
        super(props);
        this.onClickButton = this.onClickButton.bind(this);
        this.state = {count: 0};
    }

    onClickButton() {
        this.setState({count: this.state.count + 1});
    }

    render() {
        return (
          
Click Count: {this.state.count}
); }; } export default ClickCounter;

修改/src/index.js:

import React from "react";
import ReactDOM from "react-dom";
import ClickCounter from "./ClickCounter";

ReactDOM.render(, document.getElementById("root"));

运行React项目

npm run start

点击按钮,数字会随之增加。恭喜你,已经构建了一个有交互的组件!

我们还可以在React组件中定义样式。修改ClickCounter组件的render函数:

render() {
    const counterStyle = {
        margin: "16px"
    };
    return (
      
Click Count: {this.state.count}
); };
组件的prop

React组件通过定义自己能够接受的prop就定义了自己对外公共接口。外部世界通过prop和组件对话。

给prop赋值

从外部世界看prop的使用:

上面的例子使用了名为SampleButton的组件实例。React组件的prop所能支持的类型除了字符串,还可以是任何一种JavaScript语言支持的数据类型。当prop的类型不是字符串时,再JSX中必须用花括号{}把值包裹,所以style的值有两层花括号,外层代表是JSX的语法,内层代表这是个对象常量。

React组件要反馈数据给外部世界,也是用prop,因为prop类型也可以是函数,函数类型的prop等于让父组件交给子组件一个回调函数,子组件在恰当的时机调用函数的prop,就可以把信息传递给外部世界。

为了演示,我们构造一个应用包含两种组件,ControlPanel父组件,然后若干个Counter子组件。对于Counter组件,父组件ControlPanel就是外部世界:

class ControlPanel extends React.Component {
    render() {
        return (
          
); } }

React要求render只能返回一个元素,所以我们用div包裹了3个子组件。

每个Counter组件使用了caption和initValue两个prop。ControlPanel通过caption的prop传递给Counter组件实例说明文字,通过initValue的prop传递给Count组件一个初始的计数值。

读取prop值

看下Counter组件内部是如何接收prop的:

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.onClickIncrementButton = this.onClickIncrementButton.bind(this);
        this.onClickDecrementButton = this.onClickDecrementButton.bind(this);

        this.state = {
            count: props.initValue || 0
        };
    }
}

如果组件需要定义自己的构造函数,构造函数第一行一定要通过super调用父类React.Component的构造函数。给this.props赋值也是React.Component构造函数的工作之一。
在Counter的构造函数中,还给两个成员函数绑定了当前this的执行环境,因为ES6方式创建的组件并不自动给我们绑定this到当前实例对象。

在其他函数中则可以通过this.props访问传入的值,看一下render函数:

render() {
    const {caption} = this.props; // ES6的解构赋值
    return (
      
{caption} count: {this.state.count}
); };
propTypes检查

在ES6方法定义的组件中,可以通过增加类的propTypes属性来定义prop规格。在运行和静态代码检查时,都可以根据propTypes判断外部世界是否正确地使用了组件的属性。

增加Counter组件的propTypes定义:

Counter.propTypes = {
  caption: PropTypes.string.isRequired,
  initValue: PropTypes.number
};

开发过程中,定义propTypes代码可以避免犯错,但是在发布产品时,可以用babel-react-optimize工具自动去除propTypes,这样部署到产品环境的代码就会更优。

组件的state

驱动组件渲染的除了prop,还有state,state代表组件内部状态。由于React组件禁止修改传入的prop,所以当组件需要记录自身的数据变化时,就要使用state。
在Counter组件中,初始计数可以通过initValue这个prop指定。当用户点击“+”和“-”改变计数时,就要Counter组件自己通过state来存储了。

初始化state

通常在构造函数的结尾处初始化state,就如上面的Counter:

constructor(props) {
    ...
    this.state = {
        count: props.initValue || 0
    };
}

由于在PropType声明中没有用isRequired,我们需要在代码中判断给定的prop值是否存在,不存在则给一个默认值。我们可以利用React的defaultProps功能,避免判断逻辑这种充斥在构造函数之中,让代码更优。

给Counter组件添加defaultProps代码:

Counter.defaultProps = {
    initValue: 0
};

构造函数就可以简化了:

constructor(props) {
    ...
    this.state = {
        count: props.initValue
    };
}
读取和更新state

通过给button的onClick属性挂载点击事件处理函数,我们可以改变组件的state,以点击“+”按钮的响应函数为例:

onClickIncrementButton() {
    this.setState({count: this.state.count + 1});
}

通过this.state可以读取到组件的当前state。注意的是,改变state必须使用this.setState函数,而不能直接修改this.state。如果你违反这个操作,浏览器Console会告警。

直接修改this.state的值,只是野蛮的修改了state,却没有驱动组件重新渲染,新的值当然也不会反应在界面上。而this.setState()函数所做的事情,就是改变this.state的值后再驱动组件重新渲染。

无状态函数式组件

没有内部state,不需要组件生命周期函数。可以用纯函数的形式来表达。它做的事情只是根据输入来展示组件,没有其他副作用。可以把这种组件称为无状态函数式组件(stateless functional component)。

import React from "react";

// 用一个纯函数表示
const Hobby = (props) => 
  • {props.hobby}
  • ; export default Hobby;
    state设计原则

    创建尽量多的无状态组件,这些组件唯一关心的就是渲染数据。而在最外层,应该有一个包含state的父级别组件,用于处理各种事件、交流逻辑、修改state。对应的子组件要关心的只是传入的属性而已。

    state应该包含组件的事件回调函数可能引发UI更新的这类数据。在实际的项目中,应该是轻量化的JSON数据,尽量把数据的表现设计到最小,更多的数据可以在render中通过各种计算得到。

    prop和state对比

    prop用于定义外部接口,state用于记录内部状态;

    prop的赋值在外部世界使用组件时,state的赋值在组件内部;

    组件不应该改变prop的值,而state的存在的目的就是让组件来改变的。

    DOM操作

    大多数情况下,不需要操作DOM去更新UI,应使用setState。但是有些情况确实需要访问一些DOM(如表单的值),那么可采用refs方式来获得DOM节点。只需要加个ref属性,然后通过this.refs.name来获得对应的DOM结构。

    示例Profile组件:

    render() {
      return (
        
    ...
    ) }

    在button上添加事件,取得input的值,添加到state的值里面:

    addHobbyCallback() {
      // 用this.refs.name来取得DOM节点
      let hobbyInput = this.refs.hobby;
      let val = hobbyInput.value;
      if (val) {
        let hobbies = this.state.hobbies;
        // 添加值到数组
        hobbies = [...hobbies, val];
        // 更新state, 刷新UI
        this.setState({
          hobbies
        }, () => {
          hobbyInput.value = "";
        });
      }
    }

    React系列---React(一)初识React
    React系列---React(二)组件的prop和state
    React系列---React(三)组件的生命周期

    文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/83674.html

    相关文章

    • 《深入react技术栈》学习笔记()初入React世界

      摘要:用于规范的类型与必需的状态。表示由组件更改的数据,通常是通过与用户的交互来更改的。为了实现的修改,需要注册事件处理程序到相应的元素上。当事件发生时,将更新后的值是从中检索,并通知组件。通常情况下,该函数初始化状态使用,,或其他数据存储。 前言 上一篇文章中,我们讲到了JSX的一些用法和注意事项,这次我们来讲react中最基础也是特别重要的内容:组件。这篇文章包含组件的以下内容:状态、属...

      MRZYD 评论0 收藏0
    • React系列---React(三)组件生命周期

      摘要:组件装载过程装载过程依次调用的生命周期函数中每个类的构造函数,创造一个组件实例,当然会调用对应的构造函数。组件需要构造函数,是为了以下目的初始化,因为生命周期中任何函数都有可能访问,构造函数是初始化的理想场所绑定成员函数的环境。 React系列---React(一)初识ReactReact系列---React(二)组件的prop和stateReact系列---之React(三)组件的生...

      geekzhou 评论0 收藏0
    • React 深入系列3:Props State

      摘要:当真正执行状态修改时,依赖的并不能保证是最新的,因为会把多次的修改合并成一次,这时,还是等于这几次修改发生前的。下篇预告深入系列组件的生命周期新书推荐进阶之路作者徐超毕业于浙江大学,硕士,资深前端工程师,长期就职于能源物联网公司远景智能。 文:徐超,《React进阶之路》作者授权发布,转载请注明作者及出处 React 深入系列3:Props 和 State React 深入系列,深...

      endiat 评论0 收藏0
    • React 深入系列3:Props State

      摘要:深入系列,深入讲解了中的重点概念特性和模式等,旨在帮助大家加深对的理解,以及在项目中更加灵活地使用。下篇预告深入系列组件的生命周期我的新书进阶之路已上市,请大家多多支持链接京东当当 React 深入系列,深入讲解了React中的重点概念、特性和模式等,旨在帮助大家加深对React的理解,以及在项目中更加灵活地使用React。 React 的核心思想是组件化的思想,而React 组件的定...

      hiyayiji 评论0 收藏0
    • 从零开始实现一个React):实现组件功能

      摘要:在这篇文章中,我们就要实现的组件功能。这篇文章的代码从零开始实现系列是前端最受欢迎的框架之一,解读其源码的文章非常多,但是我想从另一个角度去解读从零开始实现一个,从层面实现的大部分功能,在这个过程中去探索为什么有虚拟为什么这样设计等问题。 前言 在上一篇文章JSX和虚拟DOM中,我们实现了基础的JSX渲染功能,但是React的意义在于组件化。在这篇文章中,我们就要实现React的组件功...

      vslam 评论0 收藏0

    发表评论

    0条评论

    Labradors

    |高级讲师

    TA的文章

    阅读更多
    最新活动
    阅读需要支付1元查看
    <