跳至主要內容
如何展示对话框,并给对话框传递参数?

如何展示对话框,并给对话框传递参数?

案例导入:处理对话框的误区为了方便你理解这两点,我给你举一个实际场景的例子,你就能明白为什么说在 React 中,常用的对话框是比较难处理的。比如说我们需要实现下面这个截图演示的功能:

img

那么,一般会用类似下面的代码逻辑去实现:

function MainLayout() {
  const [modalVisible, setModalVisible] = useState(false);
  const [user, setUser] = useState(null);
  const showUserModal = (user) => {
    setModalVisible(true);
    setUser(user);
  }
  return (
    <div className="main-layout">
      <Sider onNewUser={showUserModal}/>
      <UserList onEditUser={user => showUserModal(user)}/>
      <UserInfoModal visible={modalVisible} user={user} />
    </div>
  );
}

Yihui大约 7 分钟ReactReact Hooks
Hooks 实战篇

Hooks 实战篇

复杂状态处理:如何保证状态一致性?

todo!!!!

异步处理:如何向服务器端发送请求?

虽然发请求拿数据有很多种做法,但基本上都会遵循一定的规律

实现自己的 API Client

无论大小项目,在开始实现第一个请求的时候,通常我们要做的第一件事应该都是创建一个自己的 API Client,之后所有的请求都会通过这个 Client 发出去。而不是上来就用 fetch 或者是 axios 去直接发起请求,因为那会造成大量的重复代码。

通常来说,会包括以下几个方面:


Yihui大约 9 分钟ReactReact Hooks
Hooks :如何正确理解函数组件的生命周期?

Hooks :如何正确理解函数组件的生命周期?

比如对于在第三讲介绍的例子,一个用于显示博客文章的组件接收一个文章的 id 作为参数,然后根据这个 id 从服务器端获取文章的内容并显示出来。那么当 id 变化的时候,你就需要检测到这个变化,并重新发送请求,显示在界面上。在 Class 组件中,你通常要用如下的代码实现:

class BlogView extends React.Component {
  // ...
  componentDidMount() {
    // 组件第一次加载时去获取 Blog 数据
    fetchBlog(this.props.id);
  }
  componentDidUpdate(prevProps) {
    if (prevProps.id !== this.props.id) {
      // 当 Blog 的 id 发生变化时去获取博客文章
      fetchBlog(this.props.id);
    }
  }
  // ...
}

Yihui大约 4 分钟ReactReact Hooks
Hooks(2):避免重复定义回调函数

Hooks(2):避免重复定义回调函数

useCallback:缓存回调函数

在 React 函数组件中,每一次 UI 的变化,都是通过重新执行整个函数来完成的,这和传统的 Class 组件有很大区别:函数组件中并没有一个直接的方式在多次渲染之间维持一个状态。

比如下面的代码中,我们在加号按钮上定义了一个事件处理函数,用来让计数器加 1。但是因为定义是在函数组件内部,因此在多次渲染之间,是无法重用 handleIncrement 这个函数的,而是每次都需要创建一个新的:

function Counter() {
  const [count, setCount] = useState(0);
  const handleIncrement = () => setCount(count + 1);
  // ...
  return <button onClick={handleIncrement}>+</button>
}

Yihui大约 9 分钟ReactReact Hooks
React Hooks 基础

React Hooks 基础

img

思考 React 组件的本质

React 组件的模型其实很直观,就是从 Model 到 View 的映射,这里的 Model 对应到 React 中就是 state 和 props。如下图所示:

img

Yihui大约 8 分钟ReactReact Hooks
内置 Hooks(1):如何保存组件状态和使用生命周期?

内置 Hooks(1):如何保存组件状态和使用生命周期?

useState:让函数组件具有维持状态的能力

在第一讲中,你已经知道了 state 是 React 组件的一个核心机制,那么 useState 这个 Hook 就是用来管理 state 的,它可以让函数组件具有维持状态的能力。也就是说,在一个函数组件的多次渲染之间,这个 state 是共享的。下面这个例子就显示了 useState 的用法:

import React, { useState } from 'react';

function Example() {
  // 创建一个保存 count 的 state,并给初始值 0
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>
        +
      </button>
    </div>
  );
}

Yihui大约 8 分钟ReactReact Hooks
自定义 Hooks

自定义 Hooks

自定义 Hooks 在形式上其实非常简单,就是声明一个名字以 use 开头的函数,比如 useCounter。这个函数在形式上和普通的 JavaScript 函数没有任何区别,你可以传递任意参数给这个 Hook,也可以返回任何值。

但是要注意,Hooks 和普通函数在语义上是有区别的,就在于函数中有没有用到其它 Hooks。

什么意思呢?就是说如果你创建了一个 useXXX 的函数,但是内部并没有用任何其它 Hooks,那么这个函数就不是一个 Hook,而只是一个普通的函数。但是如果用了其它 Hooks ,那么它就是一个 Hook。


Yihui大约 7 分钟ReactReact Hooks
React 实现按需加载

React 实现按需加载

如何控制好整个应用的大小,以及如何提升加载性能,才能确保应用的打开速度够快。

照此来看,为了提高首屏加载速度,我们就需要对应用进行分包。首先,在打开某个页面时,只加载这个页面相关的内容,也就是按需加载。同时,为了提升后续应用的打开速度,就需要采用高效的缓存策略,避免前端资源的重复下载。

如何实现按需加载?

使用 import 语句,定义按需加载的起始模块

所谓按需加载,就是指在某个组件需要被渲染到页面时,才会去实际地下载这个页面,以及这个页面依赖的所有代码。比如当用户打开 /users/profile 这个页面时,才会真正加载对应组件的代码。如下图所示,就展示了这样一个结构,其中 Profile Page 就是需要动态加载的组件。


Yihui大约 3 分钟ReactReact Hooks
函数组件设计模式

函数组件设计模式

所谓设计模式,就是针对特定场景,提供一种公认的最佳实践。

容器模式:实现按条件执行 Hooks

Hooks 必须在顶层作用域调用,而不能放在条件判断、循环等语句中,同时也不能在可能的 return 语句之后执行。换句话说,Hooks 必须按顺序被执行到。

这个规则存在的原因就在于,React 需要在函数组件内部维护所用到的 Hooks 的状态,所以我们无法在条件语句中使用 Hooks,这因而会给我们实现业务逻辑带来一定的局限。


Yihui大约 4 分钟ReactReact Hooks
自定义事件

自定义事件

在 React 中,父子组件的交互是通过 props。这个机制其实是双向的,父组件通过 props 把值传递给子组件,而子组件则通过暴露一些事件,给父组件反馈到一些状态或数据,这两个环节是组件之间通信的基础。

在 React 中使用原生事件

在 React 中进行事件监听的语法,和原生 DOM 事件的写法是非常类似的,都是在一个节点上加一个回调函数的属性来实现。比如下面的方式:

<button onClick={handler}>Hello</button> 

Yihui大约 5 分钟ReactReact Hooks