react相关基础

# React

# 生命周期

# 图示

React 16.3 版本之前 生命周期

c

React 新版 生命周期

react生命周期new

# 组件通信

  • props,父子通信
  • 回调函数,子父通信
  • 变量提升,兄弟组建通信
  • Context,跨组建通信
  • node的events模块的单例通信
  • redux共享数据通信

# 样式配合

# 样式化加载

有多种方法可用于对 React 组件进行样式设置,每种方法各有利弊。要提到的主要是:

  • 内联样式:适用于原型设计,但有局限性(例如,无伪类样式)
  • 基于类的CSS样式:比内联样式更高效,并且对 React 刚接触的开发人员来说是熟悉的
  • JS样式中的CSS:有许多库允许将样式在组件内声明为 JavaScript,从而将样式更像代码。

参考文章:react-components-styling-options (opens new window)

  • inline CSS
  • normal CSS
  • CSS in JS libraries
  • CSS Modules
  • Sass & SCSS
  • Less
  • Stylable

# 前端富文本实现

const rawHtml = '<div><p>Title</p></div>'
const rawHtmlData = {
    __html: rawHtml // 这里有个下划线
}
return <div dangerouslySetInnerHTML={rawHtmlData}></div>
1
2
3
4
5

# jsx

每个 JSX 元素只是调用 React.createElement(component, props, ...children) 的语法糖。因此,使用 JSX 可以完成的任何事情都可以通过纯 JavaScript 完成

本质:JSX => React.createElement() => 虚拟DOM (JS对象) => 真实DOM

# 为什么使用jsx的组件中没有看到使用react却需要引入react?

本质上来说JSX是React.createElement(component, props, ...children)方法的语法糖。在React 17之前,如果使用了JSX,其实就是在使用React, babel 会把组件转换为 CreateElement 形式。在React 17之后,就不再需要引入,因为 babel 已经可以帮我们自动引入react。

# 如何 React.createElement ?

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
)
1
2
3
4
5

上述代码如何使用 React.createElement 来实现:

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);
1
2
3
4
5

# Hooks

# 10个API

# useEffet

我们可以理解成它替换了componentDidMount, componentDidUpdate, componentWillUnmount 这三个生命周期,但是它的功能还更强大。

包含3个生命周期的代码结构

// => componentDidMount/componentDidUpdate
useEffect(() => {
    // 这里的代码块 等价于 componentDidMount
    // do something...
    
    // return的写法 等价于 componentWillUnmount 
    return () => {
       // do something...
    };
  },
  // 依赖列表,当依赖的值有变更时候,执行副作用函数,等价于 componentDidUpdate
  [ xxx,obj.xxx ]
);
1
2
3
4
5
6
7
8
9
10
11
12
13

注意:依赖列表是灵活的,有三种写法

  • 当数组为空 [ ],表示不会应为页面的状态改变而执行回调方法【即仅在初始化时执行,componentDidMount】,
  • 当这个参数不传递,表示页面的任何状态一旦变更都会执行回调方法
  • 当数组非空,数组里的值一旦有变化,就会执行回调方法

# 模拟React的生命周期

  • constructor:函数组件不需要构造函数。你可以通过调用 useState 来初始化 state。
  • componentDidMount:通过 useEffect 传入第二个参数为[]实现。
  • componentDidUpdate:通过 useEffect 传入第二个参数为空或者为值变动的数组。
  • componentWillUnmount:主要用来清除副作用。通过 useEffect 函数 return 一个函数来模拟。
  • shouldComponentUpdate:你可以用 React.memo 包裹一个组件来对它的 props 进行浅比较。来模拟是否更新组件。
  • componentDidCatch and getDerivedStateFromError:目前还没有这些方法的 Hook 等价写法,但很快会加上。

# 性能优化

# 总括

性能优化,永远是面试的重点,性能优化对于 React 更加重要

  • 在页面中使用了setTimout()addEventListener()等,要及时在componentWillUnmount()中销毁
  • 使用异步组件
  • 使用 React-loadable 动态加载组件
  • shouldComponentUpdate(简称SCU )、React.PureComponentReact.memo
  • 不可变值 ImmutableJS
shouldComponentUpdate (nextProps, nextState) {
    return true // 可以渲染,执行 render(),默认返回 true
    return false // 不能渲染,不执行 render()
}
1
2
3
4

# 详细分类

# 什么情况下需要使用 shouldComponentUpdate

在React中,默认情况下,如果父组件数据发生了更新,那么所有子组件都会无条件更新 !!!!!! 通过shouldComponentUpdate()retrun fasle 来判断阻止 Header 组件做无意义的更新 shouldComponentUpdate()并不是每次都需要使用,而是需要的时候才会优化

class App extends React.Component {
    constructor () {
        this.state = { list: [] }
    }
    render () {
        return (
            <div>
                {/* 当list数据发生变化时,Header组件也会更新,调用 render() */}
                <Header />
                <List data={this.state.list}
            </div>
        )
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

shouldComponentUpdate()判断中,有一个有意思的问题,解释为什么 React setState() 要用不可变值

// 父组件中
changeList () {
    this.state.list.push({id: 2})
    this.setState({
        list: this.state.list
    })
}
// 子组件中
import _ from 'lodash'
shouldComponentUpdate(nextProps, nextState) {
    // 数组深度比较(一次性递归到底,耗费性能,工作中慎用)
    if (_.isEqual(nextProps.list, this.props.list)) {
        return false // 相等,不渲染
    }
    return true // 不相等,渲染
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

子组件将始终不会渲染,因为在shouldComponentUpdate()中,this.state.list.push()已经修改了this.props.list,而this.setState()修改了nextProps.list所以两个值深度比较,将始终相同。

# PureComponent 和 memo

  • class类组件中用PureComponent,无状态组件(无状态)中用memo
  • PureComponent, SCU中实现了浅比较
  • 浅比较已使用大部分情况(尽量不要做深度比较)

PureComponent 与普通 Component 不同的地方在于,PureComponent自带了一个shouldComponentUpdate(),并且进行了浅比较

// memo用法
function MyComponent (props) {
    /* 使用 props 渲染 */
}
// areEqual 也可不传
function areEqual(prevProps, nextProps) {
    if (prevProps.seconds===nextProps.seconds) {
        return true
    } else {
        return false
    }
}
export default React.memo(MyComponent, areEqual)
1
2
3
4
5
6
7
8
9
10
11
12
13

# immutable.js

  • 彻底拥抱“不可变值”
  • 基础共享数据(不是深拷贝),速度快
  • 有一定学习和迁移成本

# 参考链接

https://zh-hans.reactjs.org/docs/getting-started.html

上次更新: 2022/04/15, 05:41:33
×