核心属性

Misaka10032面向组件编程三大核心属性类式组件大约 3 分钟

注意,本章主要以类式组件为例,记录 React 中的核心属性与方法

state

描述

state 是组件对象最重要的属性,值是对象(可以包含多个 key-value 的组合)

组件被称为“状态机”,通过更新组件的 state 来更新对应的页面显示(重新渲染组件)

注意

组件中 render 方法中的 this 为组件实例对象

组件自定义的方法中 this 为 undefined,如何解决?

  • 方案一:强制绑定 this,通过函数对象的 bind()
  • 方案二:箭头函数

更新

state 中存放的是状态数据,不能直接修改或更新

需使用原型方法setState()来切换状态,this.setState({ flag: 'xxx' }),属于状态对象合并

Component 组件示例

import { Component } from "react";

export default class Count extends Component {
  state = {
    count: 0,
  };

  add = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <div>{this.state.count}</div>
        {/* 注意,此处禁止写 this.state.count++,因为自增运算符是对原count值的修改,React禁止对state的直接修改 */}
        <button onClick={this.add}>计数按钮</button>
      </div>
    );
  }
}

props

描述

每个组件对象都会有 props(properties)属性

组件标签的所有属性都保存在 props 中

注意

props 是通过标签属性从组件外部向组件内部传递变化的数据(自上而下的数据通信)

子组件内部不要修改 props 数据

操作

  1. 子组件读取 props

this.props.nameopen in new window

  1. 对 props 中的属性值进行类型限制和必要性限制

第一种方式(弃用)

// 类名外部写法
Person.propTypes = {
  name: React.PropTypes.string.isRequired,
  age: React.PropTypes.number,
};
// 类名内部写法
class Person {
  static propTypes = {
    name: React.PropTypes.string.isRequired,
    age: React.PropTypes.number,
  };
}

第二种方式(推荐,使用 prop-types 库进限制(需要引入 prop-types 库))

// 类名外部写法
Person.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number.
}
// 类名内部写法
class Person {
  static propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number,
  }
}
  1. 扩展运算

将对象的所有属性通过 props 传递

<Person {...person}></Person>
  1. 默认属性
Person.defaultProps = {
  age: 18,
  sex: "男",
};
  1. 组件类的构造函数
// 组件初始化时可以对props进行操作
constructor(props) {
  super(props);
  console.log(props);
}
  1. 函数式组件可传入 props,但不可使用 state 属性
function App(props) {
  const { name, age, msg } = props;
  return <div>名字:{name}</div>;
}

Component 组件示例

import React, { Component } from "react";
import Item from "../item/index";
import "./index.css";

class ToDoList extends Component {
  state = {
    listState: true,
  };

  render() {
    const toDoList = {
      handleData: this.props.handleData,
      listState: this.state.listState,
    };
    return (
      <ul className="doList">
        {this.props.toDoList.map((item) => {
          return <Item key={item.id} {...toDoList} content={item} />;
        })}
      </ul>
    );
  }
}

export default ToDoList;
import React, { Component } from "react";
import "./index.css";

class Item extends Component {
  render() {
    const { id, value, checked } = this.props.content;
    const listState = this.props.listState;
    const handleData = this.props.handleData;
    return (
      <li>
        <input
          onChange={handleData({ eventId: id, flag: listState })}
          type="checkbox"
          checked={checked}
        />
        <p
          suppressContentEditableWarning
          contentEditable={true}
          onBlur={handleData({ eventId: id, flag: listState, mod: true })}
          className="doContent"
        >
          {value}
        </p>
        <div
          onClick={handleData({ eventId: id, flag: listState, del: true })}
          className="removeList"
        >
          -
        </div>
      </li>
    );
  }
}

export default Item;

refs

描述

组件内的标签可以定义 ref 属性来标识自己

注意

在 render 函数中,ref 指向的组件如this.refs.xxx为 undefined,因为此时组件尚未挂载,ref 指向为空

操作

  1. 字符串形式的 ref(建议弃用)

<input ref="input1" />

  1. 回调形式的 ref

<input ref={(c)=>{this.input1 = c}}>

  1. createRef 创建的 ref 容器(建议使用)

myRef = React.createRef()

<input ref={ this.myRef } />

Component 组件示例

import { Component, createRef } from "react";

export default class Count extends Component {
  count = createRef();

  add = () => {
    this.count.current.innerText++;
  };

  render() {
    return (
      <div>
        <div ref={this.count}>0</div>
        {/* 注意,此处禁止写 this.state.count++,因为自增运算符是对原count值的修改,React禁止对state的直接修改 */}
        <button onClick={this.add}>计数按钮</button>
      </div>
    );
  }
}

三大属性执行次数

render 调用 N+1 次,第一次为初始化,每次修改调用都会重新调用 render

state 执行 N 次,render 初始化时赋值 state 初始值,每次修改都会重新设置 state(如果 state 涉及修改的话)

props 受父组件影响,父组件执行 N 次则 props 执行 N 次(如果 props 涉及修改的话)

回调 ref 以内联函数的方式定义,在更新过程中被执行两次,第一个传入参数为 null,第二次再传入 DOM 元素。所以目前最推荐的还是React.createRef()方法