【React初接触】(一)关于组件声明

328 阅读4分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

前情:换工作 + 换技术栈同时进行 QAQ

Virtual DOM

React把 真实DOM树 转换为 JavaScript对象树(VirtualDOM)。每次更新后,重新计算 Virtual DOM,并和上一次的进行对比,对发生变化的部分做批量更新。React也提供了 shouldComponentUpdate 生命周期函数,减少数据变化后不必要的对比过程,以保证性能。

优点:

  1. 提升性能,优化渲染方式
  2. 便于和其他平台集成(React-native、React-router-dom)

构建:

React通过创建和更新 虚拟元素virtual element 来管理整个 virtual DOM

React创建的虚拟元素分为:

  1. DOM元素
<button class="btn btn-blue">
    <em>confirm</em>
</button>


// ---- json --- virtual element ----
{
  type: 'button',
  props: {
    className: 'btn btn-blue',
    children: {
      type: 'em',
      props: {
        children: 'confirm'
      }
    }
  }
}
  1. 组件元素
const Button => ({ color, text }) {
  return {
    type: 'button',
    props: {
      className: `btn btn-${color}`,
      children: {
        type: 'em',
        props: {
          children: text
        }
      }
    }
  }
}

// ---- json --- virtual element --- Button('blue', 'Confirm') ----
{
  type: 'Button',
  props: {
    color: 'blue',
    text: 'Confirm'
  }
}

组件声明

class声明组件

【ShopingList】React 组件类 / 组件类型。接受 props,通过 render 方法返回需要展示在屏幕上的视图的层次结构。

render方法的返回一个React元素,描述屏幕上看到的内容

class ShopingList extends React.Component {
    state = {
        value: '',
        visible: false
    }
  	
    handleVisible = (visible:boolean) => {
      this.setState({ visible }, () => {
        // 处理visible之后回调
      });
    };

    render() {
        const { message } = this.props;
        const { value, visible } = this.state;
        return {
            <div>{message}</div>
        }
    }
}

export { ShopingList }

// 或者 React.PureComponent { .... }

React.PureComponent

React.Component 类似。React.PureComponent 通过浅层对比 prop 和 state 的方式,实现了 shouldComponentUpdate()

  1. 如果赋予 React组件 相同的 props 和 state,render()函数会渲染相同的内容,那么在某些情况使用 pureComponent 可以提高性能

  2. React.PureComponent 中的 shouldComponentUpdate() 仅作对象的浅层比较,如果对象数据结构复杂,可能会因为无法检查深层变化导致错误。所以仅在数据结构简单时使用,或者深层数据结构发生变化的时候,使用 forceUpdate() 来确保组件更新

  3. React.PureComponent 中的 shouldComponentUpdate() 将跳过所有子组件树的 prop 更新,需要确保所有子组件也都使用React.PureComponent声明。

React.memo

高阶组件,和 React.PureComponent类型,但只适用于函数组件。

  1. 如果函数组件在给定 相同props 会渲染相同内容,那么可以将其包装在 memo 中调用,通过 记忆组件 渲染结果的方式提高组件性能。(React 将跳过渲染组件,直接复用最近一次渲染的结果)

  2. memo 仅检查 props变更。如果函数组件被 memo 包裹,且实现过程中出现 useStateuseContexthook,那么当 context 发生变化时,仍会触发重新渲染

  3. 默认情况仅对复杂对象做浅层对比,如果需要控制比对过程,需要传入第二个参数(自定义比较函数)

const Animal = React.memo(function Animal(props) {
  // 使用props渲染
})


// --------- 自定义函数 ------------
function Animal(props) {
  // 使用props渲染
}
function areEqual(prevProps, nextProps) {
  // 自定义比对:return 两个传参 render方法 返回结果是否相同(true/false)
}
export default React.memo(Animal, areEqual)

React.FC

const ShopingList: React.FunctionComponent<{message:string}> = (props: any) => {
  const { visible } = props;
    const handleVisible = (props:any) => { 
        // ....
    }
  return ( <div>{message}</div> )
};

// FunctionComponent 简写成 FC
const ShopingList: React.FC<{ message:string}> = ({ message }) => (
  <div>{message}</div>
);

对比三种组件创建方式:

  • React.Component 通用的创建方式,万能但不能提高组件性能

  • React.PureComponent 浅层对比判断 shouldComponentsUpdate。传入相同 propsstate不触发组件更新。针对传入简单数据类型的propsstate使用,或使用 forceUpdate 强制触发更新。

  • React.memo 记忆组件,仅针对函数组件。相同props将会直接使用最近一次渲染结果,不触发更新。针对传入简单数据类型的props使用,或者传入第二个参数作为自定义比较函数。

以上三种都是class组件,可以认为是一种声明方式,只是使用了不同的React方法,区别在于方法内对组件重新渲染节点的优化。

函数组件

接受唯一带有数据的props对象,并返回一个react元素。本质上是 js函数

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

---- 写在代码 -- 箭头函数 -----

export default (props) => {
    return ( ... )
}

不知道怎么用就用函数组件!!!先把代码码出来再管优化。

渲染组件

自定义组件必须以大写字母开头

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>
}
const element = <Welcome name="Sara"/>
ReactDOM.render(
    element,
    document.getElementById('root')
)

/*
1. 调用 ReactDOM.render() 函数,并传入 Welcome组件 作为参数
2. React调用 Welcome组件,并将 { name: 'Sara' } 作为 props 传入
3. Welcome组件 将 h1元素 作为返回值
4. React DOM 将 DOM 更新为 <h1>Hello, Sara</h1>
*/