React基础

153 阅读4分钟

生命周期

image.png

1. constructor

constructor 是类通用的构造函数,常用于初始化,算是生命周期的一环。React 后来的版本中类组件也可以不写。

注意:在构造函数中使用时,super 关键字将单独出现,并且必须在使用 this 关键字之前使用。super 关键字也可以用来调用父对象上的函数。MDN 说明

  class JJTest extends React.Component {
      // constructor 写法
      constructor(props) {
        super(props);
        this.state = {
          count: 0,
        };
        this.handleClick = this.handleClick.bind(this);
      }
      // 直接声明
      state = {
        count: 0,
      };
  }

2. getDerivedStateFromProps

触发时机:state 变化、props 变化、forceUpdate,如上图。

这是一个静态方法, 是一个和组件自身"不相关"的角色. 在这个静态方法中, 除了两个默认的位置参数 nextProps 和 currentState 以外, 你无法访问任何组件上的数据。

// 初始化/更新时调用
static getDerivedStateFromProps(nextProps, currentState) {
  console.log(nextProps, currentState, "getDerivedStateFromProps方法执行");
  // 返回值是对currentState进行修改
  return {
    fatherText: nextProps.text,
  };
}

3、render

render 函数返回的 JSX 结构,用于描述具体的渲染内容, render 被调用时,它会检查 this.props 和 this.state 的变化并返回以下类型之一:

React 元素。通常通过 JSX 创建。例如,

会被 React 渲染为 DOM 节点, 会被 React 渲染为自定义组件,无论是

还是 均为 React 元素。

数组或 fragments。使得 render 方法可以返回多个元素。欲了解更多详细信息,请参阅 fragments 文档。

Portals。可以渲染子节点到不同的 DOM 子树中。欲了解更多详细信息,请参阅有关 portals 的文档

字符串或数值类型。它们在 DOM 中会被渲染为文本节点

布尔类型或 null。什么都不渲染。(主要用于支持返回 test && 的模式,其中 test 为布尔类型。)

注意:如果 shouldComponentUpdate() 返回 false,则不会调用 render()。

Hooks 不需要写 render 函数。要注意的一点是,即使 Hooks 不需要写 render, 没有用到 React.xxx,组件内还是要import React from "react";的(至于原因,后续深入 Hooks 学一下,大哥们也可以解释下)。React 官方也说了,后续的版本会优化掉这一点。

4、componentDidMount

主要用于组件加载完成时做某些操作,比如发起网络请求或者绑定事件。当做 vue 的 mounted 用就行了,这里需要注意的是:

componentDidMount() 里直接调用 setState()。它将触发额外渲染,也就是两次 render,不过问题不大,主要还是理解。

5、shouldComponentUpdate

该方法通过返回 true 或者 false 来确定是否需要触发新的渲染。因为渲染触发最后一道关卡,所以也是性能优化的必争之地。通过添加判断条件来阻止不必要的渲染。注意:首次渲染或使用 forceUpdate() 时不会调用该方法。

React 官方提供了一个通用的优化方案,也就是 PureComponent。PureComponent 的核心原理就是默认实现了 shouldComponentUpdate 函数,在这个函数中对 props 和 state 进行浅比较,用来判断是否触发更新。

当然 PureComponent 也是有缺点的,使用的时候一定要注意:由于进行的是浅比较,可能由于深层的数据不一致导致而产生错误的否定判断,从而导致页 面得不到更新。不适合使用在含有多层嵌套对象的 state 和 prop 中。

shouldComponentUpdate(nextProps, nextState) {
  // 浅比较仅比较值与引用,并不会对 Object 中的每一项值进行比较
  if (shadowEqual(nextProps, this.props) || shadowEqual(nextState, this.state) ) {
    return true
  }
  return false
}

6、getSnapshotBeforeUpdate

在 DOM 更新前被调用,返回值将作为 componentDidUpdate 的第三个参数。

getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log("getSnapshotBeforeUpdate方法执行");

    return "componentDidUpdated的第三个参数";
}

7、componentDidUpdate

首次渲染不会执行此方法。可以使用 setState,会触发重渲染,但一定要小心使用,避免死循环

componentDidUpdate(preProps, preState, valueFromSnapshot) {
    console.log("componentDidUpdate方法执行");

    console.log("从 getSnapshotBeforeUpdate 获取到的值是", valueFromSnapshot);
  }

8、componentWillUnmount

主要用于一些事件的解绑,资源清理等,比如取消定时器,取消订阅事件

JSX

1、循环列表

jsx 中一般用 map 来渲染列表循环类的,vue 中直接在 template 中写 v-for 即可

{
  list.map((item, index) => {
    return <AppCard key={index} title={item.title} onClick={item.onClick} />;
  });
}

2、样式

  1. className

单独写一个 class 是可以的,动态拼接需要借助 classnames 库

import style from './style.css'

<div className={style.class1 style.class2}</div>
  1. style

需要注意的:两个括号(样式被当做一个对象来解析),类似-连接的样式属性需要转换成小驼峰写法

<div style={{ marginTop: 8 }}>样式</div>
  1. css 隔离

u1s1,css 隔离这块还是 vue 的 scoped 好用

css-module create-react-app 中内置了使用 CSS Modules 的配置,和 vue 的 scoped 原理相似,都是在生成的 class 后面加了 hash 值

// style.module.css
.text {
    color: blue
}
// app.tsx
import s from "./style.module.css";
class App extends Component {
  render() {
    return <div className={s.text}>css-module text</div>;
  }
}
// 编译后
.text_3FI3s6uz {
    color: blue;
}