React.md

简书迁移

Posted by thrfox on June 29, 2020

状态和生命周期

组件转换为一个类

类即包含有自己特定的功能

如一个Clock组件转换为Clock类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Clock(props){
    return (
    <h1>time is : {props.date.toLocaleTimeString()}</h1>
    );
}

function tick(){
  ReactDOM.render(
    <Clock date = {new Date()}/>,  //需要传入参数date
    document.getElementById('root')
  )
}

setInterval(tick, 1000);

转换为类并加上生命周期 componentDidMount()为每次组件内render()插入DOM完成后,加载一次 componentWillUnmount()为组件移除DOM之前执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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 (
    <h1>time is : {this.state.date.toLocaleTimeString()}</h1>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
)
分为5个步骤:
  1. 通过ReactDOM.render()调用Clock的construtor;当Clock需要显示当前时间的时候,它带着Date对象将this.state进行初始化。稍后对this.state进行更新。

  2. Clock调用construtor之后,调用render()方法。该render()使React渲染出DOM。
  3. 当Clock插入DOM结束后,会调用componentDidMount()生命周期方法,在此方法里,会请求浏览器调用定时器(setInterval),该定时器每秒调用tick()方法一次
  4. 每秒浏览器调用tick()方法时,组件中的state状态被tick()方法中的setState()改变了,为创建一个Date对象。setState()调用后,会调用shouldComponentUpdate判断是否需要重新render(),此时的this.state.date已经与之前不同了
  5. 如果之后Clock组件从DOM中被移除了,则会执行componentWillUnmount(),终止tick()中的setInterval()计时器。

控制事件

React的事件与DOM事件类似,只有一些小差别,事件名为小驼峰写法onclick为onClick

1
2
3
4
//DOM Handling events
<button onclick="activateLasers()"/>
//React
<button onClick={activateLasers}/>

在class中,如果需要注册一个事件,则需要将该事件与class进行绑定,如下例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Button extends React.Component {
  constructor(){
    super();
    this.name = "Bob";  //this指Button
    this.click3 = this.click2.bind(this);
    this.click1 = () => {
      console.log(`hello ${this.name}`);
    }
  }
  click2(){
    console.log(`hello ${this.name}`);  //this指click2
  }

  render(){
    return (
      <raw>
        <button onClick={this.click1}>Click1</button>
        <button onClick={this.click2}>Click2</button>
        <button onClick={this.click3}>Click3</button>
        <button onClick={(e) => this.click2(e)}>Click3</button>
      </raw>
    );
  }
}

// 此时click2的this非彼this,因为在click2中的this指的是click2
// click3中的this.click2.bind(this)指将class Button中的click2绑定给了class,即向上绑定
// 推荐使用click3的写法

条件渲染

根据条件可以渲染不同的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}
function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {              // 根据 isLoggenIn 渲染不同的问候语
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  // 你可以尝试设置 isLoggedIn={true}:
  <Greeting isLoggedIn={false} />,
  document.getElementById('root')
);

可以使用?和:简化运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoggedIn: false
    };
  }

  render() {
    const { isLoggedIn } = this.state;
    const button = isLoggedIn ?
          <button onClick={() => { this.setState({isLoggedIn: false}); }}>注销</button>
          : <button onClick={() => { this.setState({isLoggedIn: true}); }}>登录</button>;

    return (
      <div>
        <h1>
          {
            isLoggedIn ? 'Welcome back!' : 'Please sign up.'
          }
        </h1>
        {button}
      </div>
    );
  }
}

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

如果在某些条件下不需要渲染,return null即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function WarningBanner(props) {
  if (!props.warn) {
    return null;
  }

  return (
    <div className="warning">
      Warning!
    </div>
  );
}

ReactDOM.render(
  <WarningBanner warn={true} />,  //尝试一下false此时返回null
  document.getElementById('root')
);