【React系列】React基础

3,396 阅读3分钟

React 始终整体刷新页面

React 4个核心原则:

  1. 1个新概念:组件
  2. 4个核心 API
  3. 单向数据流
  4. 完善的错误提示

React组件类型:

  1. 受控组件 表单元素状态由使用者维护
<input 
    type="text"
    value={ this.state.value }
    onChange={evt => {
      this.setState({ value: evt.target.value })
    }}
/>
  1. 非受控组件 表单元素状态 DOM 自身维护
<input 
    type="text"
    ref={ node => { this.input = node } }
/>
  • 创建组件要遵循:职责单一原则
  • 数据状态管理要遵循:DRY 原则(don't repeat yourself)
  1. 能计算得到的状态不要单独存储
  2. 组件尽量无状态,所需数据通过 props 获取

JSX

JSX 的本质

JSX的本质是动态创建组件的语法糖

如何使用 JSX

  1. JSX 本身也是表达式
const element = <h1>hello, world!</h1>;
  1. 在属性中使用表达式
<MyComponent foo={ 1+2+3+4 } />
  1. 延展属性
const props = { firstName: "ben", lastName: "Hector" };
const greating = <Greating { ...props } />
  1. 表达式作为子元素
const element = <li>{ props.message }</li>

约定:自定义组件以大写字母开头

  1. react 认为小写的 tag 是原生的 DOM 节点,如 <div>
  2. 大写字母开头为自定义组件
  3. JSX 标记可以直接使用属性语法,这个可以不用大写字母开头,例如 <menu.Item />

React 的生命周期及其使用场景

constructor

  1. 用于初始化内部状态
  2. 唯一可以直接修改 state 的地方

getDerivedStateFromProps

  1. 当 state 需要从 props 初始化时使用
  2. 尽量不要使用:维护两者状态一致性会增加复杂度
  3. 每次 render 都会调用
  4. 典型场景:表单控件获取默认值

componentDidMount

  1. UI 渲染完成后调用
  2. 只执行一次
  3. 典型场景:获取外部资源

componentWillUnmount

  1. 组件移除时被调用
  2. 典型场景:资源释放

getSnapshotBeforeUpdate

  1. 在页面render之前调用,state 已更新
  2. 典型场景:获取 render 之前的 DOM 状态

componentDidUpdate

  1. 每次 UI 更新时被调用
  2. 典型场景:页面需要根据 props 变化重新获取数据

shouldComponentUpdate

  1. 决定 Virtual DOM 是否需要重绘
  2. 一般可以由 PureComponent 自动实现
  3. 典型场景:性能优化

Virtual DOM

  1. 广度优先分层比较,diff算法复杂度为 O(n) 从根节点开始比较
  • 如果节点顺序发生变化,根据key重新排列节点
  • 如果节点类型发生了变化,直接替换整个节点
  • 节点跨层移动,会删除原来的节点,重新创建新的节点
  1. 虚拟 DOM 的两个假设
  2. 组件的 DOM 结构是相对稳定的
  3. 类型相同的兄弟节点可以被唯一标识,主要用于节点之间位置/顺序发生变化,每个相同类型的子元素,需要用key进行唯一的标识,否则会增加开销

组件的设计模式

组件复用的两种形式:高阶组件和函数作为子组件 这两种形式都是设计模式,可是实现更多场景的组件复用

高阶组件

高阶组件接受一个已有组件作为参数,返回新的组件。一般高阶组件不会有自己的 UI展现,只是为封装的组件提供额外的功能或者数据。

函数作为子组件

class MyComponent extends React.Component {
	render() {
    	return (
        	<div>{this.props.children('Minmin')}</div>
        )
    }
}

<MyComponent>
	{(name) => (
    	<div>{name}</div>
    )}
</MyComponent>