evantianx / Bloooooooog

Place to record what I thought and learned
0 stars 0 forks source link

React学习(二)Components and Props & State and Lifecycle #5

Open evantianx opened 7 years ago

evantianx commented 7 years ago

Components and Props

组件可以将UI分割为独立,可复用块,并且以组件化方式管理这些块。

理论上来说,组件类似于JS中的函数。它们都接受任意的输入(称为'props')然后返回描述如何展现于屏幕的React elements。

函数式组件和类组件

函数式组件:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>
}

类组件:

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

渲染一个组件

React elements不仅可以由DOM标签构成,用户自定义标签也可:

const element = <Welcome name="Sara"/>

当React检测到一个elements中为自定义标签,会将JSX属性作为一个对象传递给这个组件,也即props

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>
}

const element = <Welcome name="Sara" />
ReactDOM.render(
  element,
  document.getElementById('root')
)

流程为:

  1. 调用ReactDOM.render()以及element <Welcome name="Sara">
  2. React调用Welcome组件,且将{ name: "Sara" }作为props传入
  3. Welcome组件返回<h1>Hello, Sara</h1>
  4. React DOM更新DOM

组件名字首字母一定要大写

复合组件

组件可以在输出中调用其他组件

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Tom" />
      <Welcome name="Jack" />
    </div>
  )
}

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

和Vue2.x一样,React组件必须只包含一个根节点

props是只读的

React组件必须遵循"永远不改变输入值"这一准则 在下一节中会介绍State这一个概念,如何在不违背这一准则的前提下修改状态。

State and Lifecycle

目前为止我们只学习了一种更新视图的方法(即不断地给ReactDOM.render()传入新的参数)。 如何让组件自更新,而不是依靠我们操作来实现更新呢? 方法就是state,而state只能在类组件中进行创建。

将函数组件转换为类组件

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

转换为:

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

为类组件添加本地状态

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>
    );
  }
}

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

为类组件添加生命周期方法

在拥有诸多组件的应用内,适时释放被摧毁组件占用资源是非常重要的。 我们可以选择在组件刚渲染到DOM时为Clock开启一个定时器,在组件被摧毁之前将其关闭,这些方法被称为生命周期钩子。 代码如下:

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

  //组件刚刚被渲染到DOM
  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  //组件脱离DOM
  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  //this.setState()方法用来更新状态
  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')
);

分析上述代码执行过程:

正确使用State