React基础——组件

组件从概念上看就像是函数,它可以接收任意的输入值(称之为“props”),并返回一个需要在页面上展示的React元素。

定义一个组件

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Props

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);
我们来回顾一下在这个例子中发生了什么:
  1. 我们对<Welcome name="Sara" />元素调用了ReactDOM.render()方法。
  2. React将{name:'Sara'}作为props传入并调用Welcome组件。
  3. Welcome组件将<h1>Hello,Sara</h1>元素作为结果返回。

Props的只读性

无论是使用函数或是类来声明一个组件,它决不能修改它自己的props。来看这个sum函数:

function sum(a, b) {
  return a + b;
}

类似于上面的这种函数称为“纯函数”,它没有改变它自己的输入值,当传入的值相同时,总是会返回相同的结果。

与之相对的是非纯函数,它会改变它自身的输入值:

function withdraw(account, amount) {
  account.total -= amount;
}

React是非常灵活的,但它也有一个严格的规则:

所有的React组件必须像纯函数那样使用它们的props。

当然,应用的界面是随时间动态变化的,我们将在下一节介绍一种称为“state”的新概念,State可以在不违反上述规则的情况下,根据用户操作、网络响应、或者其他状态变化,使组件动态的响应并改变组件的输出。

为一个类添加局部状态——State

state与props十分相似,但是state是私有的,完全受控于当前组件。
我们之前提到过,定义为类的组件有一些特性。state就是如此:一个功能只适用于类。

function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

我们会通过3个步骤将 date 从属性移动到状态中:

  • 在 render() 方法中使用 this.state.date 替代 this.props.date
class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
  • 添加一个类构造函数来初始化状态 this.state
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

从 元素移除 date 属性:

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

将生命周期方法添加到类中

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

它将使用 this.setState() 来更新组件局部状态

正确地使用状态

关于 setState() 这里有四件事情需要知道

  • 不要直接更新状态
    例如,此代码不会重新渲染组件:
// Wrong
this.state.comment = 'Hello';

应当使用 setState():

// Correct
this.setState({comment: 'Hello'});
  • state初始化:构造函数是唯一能够初始化 this.state 的地方
  • 状态更新可能是异步的
    React 可以将多个setState() 调用合并成一个调用来提高性能。因为 this.props 和 this.state 可能是异步更新的,你不应该依靠它们的值来计算下一个状态。

例如,此代码可能无法更新计数器:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

要修复它,请使用第二种形式的 setState() 来接受一个函数而不是一个对象。 该函数将接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

组件的生命周期

每个组件都有几个 “生命周期方法” ,您可以重写这些方法,以在过程中的特定时间运行代码。 前缀为 will 的方法在一些事情发生之前被调用,而前缀为did的方法在一些事情发生后被调用。

Mounting(装载)

当组件实例被创建并将其插入 DOM 时,这些方法将被调用:

constructor()
componentWillMount()
render()
componentDidMount()

Updating(更新)

改变 props 或 state 可以触发更新事件。 在重新渲染组件时,这些方法将被调用:

componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()

Unmounting(卸载)

当一个组件从 DOM 中删除时,这个方法将被调用:

componentWillUnmount()

其他 APIs

每个组件还提供了一些其他 API:

setState()
forceUpdate()

类属性

defaultProps
displayName

实例属性

props
state

参考文章:
State & 生命周期
React.Component
Typechecking With PropTypes

猜你喜欢

转载自blog.csdn.net/anxin_wang/article/details/79097574