React问答

阅读 1.7k

本篇总结了React最基本和核心的一些概念,通过简单的问答形式来进行介绍。

React组件

什么是React组件呢?就是一个,或者说一个构造函数

class HelloMessage extends React.Component {
  render() {
    return (
      <div>
            Hello {this.props.name}
        </div>
    );
  }
}

ReactDOM.render(
  <HelloMessage name="Olaf" />,
  document.getElementById('hello')
);

注意:React使用了JSX语法,其中,用大括号来进行逻辑处理。

React元素

大致来说,React元素分为两类:

  • 纯html:<div>hello, 100</div>
  • 自定义:<Hello />

打印出来如下:


它是一个对象,其中有propsrefkeytype等属性。它本质是通过 React.createElement() 来进行创建的。

props和state

  • Props:为了解决父组件传值给子组件的问题
  • State:是为了维护组件内部的数据状态

React常用的生命周期

React有一系列声明周期过程,其中最重要的一个是 componentDidMount,它表明组件已经挂载到DOM节点上了 ,常用于ajax请求。与之对应的是 componentWillUnmount,表明组件已经从DOM节点上卸载了,这时,可以进行清除事件等操作。

其次,还有 shouldComponentUpdate ,如果返回false,则组件不会更新渲染,常用于优化性能。

最后,请注意render()方法的执行顺序,完整生命周期图如下:


当组件更新时,会执行哪些生命周期?

如上图,过程如下:

  • shouldComponentUpdate
  • componentWillUpdate
  • render()
  • componentDidUpdate

如果是父组件的props发生改变而导致的更新,那么在shouldComponentUpdate发生之前,还会有componentWillReceiveProps方法会被执行。

Ref

ref可以绑定到任何组件上,获得该组件的真实DOM节点。如果不用ref,就只能通过获取DOM节点的方式,比如document.getElementById()来获取DOM节点。

React中的循环渲染

在循环渲染时,需要注意记得指定key

const listItems = numbers.map((number) =>
    <li key={number.toString()}>
         {number}
          </li>
);

return (
    <ul>{listItems}</ul>
);

一般使用map()来进行映射渲染。

受控组件和不受控组件

将值直接用React的状态进行绑定,这样,组件就完全受React的状态控制了,称为受控组件

<input type="text" value={this.state.value} onChange={this.handleChange} />

如上代码中,input的值完全取决于state中的value的值。

反之,其组件内部的值没有和React中的状态关联起来,来看一个例子:

<input type="text" ref={dom => this.input = dom} />

上面的input中,其自身就包含value值,其值并不受React中的state来管理和控制,为其自身所拥有,称为不受控组件,可以通过 this.input.current.value 来获得其本身的值。

React中的内联样式

React的内联样式是一个对象:

const style = {background: 'blue'}

<div style={style}>

但在实际开发中,更多地会使用命名css类这种方式,常常搭配classnames库来使用。

组件间的常见通信方式

React组件之间常常会需要相互间进行通信,根据其特征的不同,一般分为如下三种:

  • 子组件通知父组件

这是最常见的方式,直接用 this.props.xxx() 事件即可。在父组件中捕获来自子组件的事件:

<ChildPart onChange={() => console.log('from child')}/>

子组件中的定义如下:

class ChildPart extends React.Component {
    render() {
        return (
            <button onClick={() => this.props.onChange()}>
                       Hello {this.props.name}
                 </button>
        );
    }
}

ChildPart组件中,当点击button时,触发onClick事件,引发this.props.onChange()执行,从而触发事件到父组件中,最终打印from child字符串。

  • 父组件通知子组件

父组件可以使用props来给子组件传值,但是props并不能直接触发子组件的事件。所以,需要通过ref绑定子组件后,才可以直接访问子组件中的方法和属性。父组件的定义如下:

class Father extends React.Component {
    render() {
        return (
            <div>
                      <ChlildPart ref={node => this.childPart = node} />
                      <button onClick={() => this.childPart.handleClick('father clicked button')}>Button</button>
                </div>
        );
    }
}

定义了一个父类组件Father,并用refthis.childPart指向子组件ChildPart的DOM节点,当点击父类中的button时,触发onClick事件,接着执行this.childPart.handleClick('father clicked button')引发子组件中定义的handleClick方法执行。

子组件ChildPart的定义如下:

class ChlildPart extends React.Component {
    handleClick = value => {
        console.log('msg from father: ', value)
    }

    render() {
        return (
            <h2>child part</h2>
        );
    }
}
  • 没有嵌套关系的组件之间通信

可以使用events模块的 EventEmitter类,来构建一个公共的event bus来进行管理。

性能优化

React中的性能优化,核心的要点就是减少 render 的次数,避免无谓的渲染,常用的处理方式有:

  • 调整组件间的结构,使状态内移,防止父组件状态的更改触发过多子组件的渲染。
  • PureRender,但PureRender只是浅比较。

setState后组件会马上更新吗?

不会,setState是异步的。

组件开发的原则

组件就像积木,在搭建房子之前,需要仔细考虑它们之间的关联。

React引入hooks的初衷是什么?

  • 在组件之间复用状态逻辑很难
  • 复杂组件变得难以理解
  • 难以理解的 class

参考

最后编辑于: 2022-06-28

评论(0条)

(必填)
复制成功