响应式编程与React | 青训营笔记

20 阅读8分钟

这是我参与「第五届青训营 」笔记创作活动的第11天

一、本堂课重点内容:

  1. React的历史与应用
  2. React的设计思路
  3. React(hooks)的写法
  4. React的实现
  5. React状态管理库
  6. 应用级框架科普

二、详细知识点介绍:

React的历史与应用

image.png

image.png

React的设计思路

React是一种用于构建用户界面的JavaScript库。它的设计思路主要体现在以下几个方面:

  1. UI编程痛点: React通过使用虚拟DOM,有效地减少了重新渲染界面的性能消耗,从而解决了传统UI编程中频繁操作DOM带来的性能问题。

  2. 组件化: React采用了组件化的思想,将界面拆分成若干个组件,每个组件可以单独进行状态管理和渲染。这样可以使代码更加结构化、可维护性更高。

    例如,下面的代码是一个简单的 React 组件,它渲染了一个输入框和一个按钮。

    class InputField extends React.Component {
      render() {
        return (
          <div>
            <input type="text" placeholder="Enter something" />
            <button>Submit</button>
          </div>
        );
      }
    }
    

    这段代码简单明了,而且可重用,可以把这个组件用在其他地方而不用再重新写一遍。

    <InputField />
    
  3. 响应式与转换式: React采用了转换式编程思想,即将状态转换为视图的过程,而不是直接操作DOM。这样可以使组件的状态变化能够及时地反映在界面上,实现响应式编程。

    例如,我们可以在上面的组件中添加一个状态来保存输入框中的文本值,并在输入框中输入文本时,将状态更新为当前输入的文本。

    class InputField extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          inputValue: ""
        };
      }
    
      handleChange = event => {
        this.setState({ inputValue: event.target.value });
      };
    
      render() {
        return (
          <div>
            <input
              type="text"
              placeholder="Enter something"
              value={this.state.inputValue}
              onChange={this.handleChange}
            />
            <button>Submit</button>
          </div>
        );
      }
    }
    
    
  4. 状态归属问题: React 使用单向数据流来解决状态归属问题。状态应该由组件自己管理,而不应该由其他组件或全局状态管理。这样可以使组件变得更加独立和可维护。

  5. 生命周期: 生命周期: React 组件有多个生命周期函数可供使用,例如 componentDidMountcomponentDidUpdatecomponentWillUnmount。这些生命周期函数可以帮助开发者在组件的不同阶段执行特定的操作,比如在组件挂载后执行一些初始化操作,在组件卸载前执行一些清理操作。

    class InputField extends React.Component {
        componentDidMount() {
            console.log("InputField mounted!");
        }
    
        componentWillUnmount() {
            console.log("InputField is about to be unmounted!");
        }
        //...
    }
    

总之,React 的设计思路是通过组件化、响应式与转换式编程、单向数据流和生命周期函数来简化 UI 编程,使开发者能更轻松地编写和维护应用程序的 UI 部分。

React(hooks)的写法

React Hooks 是 React 16.8 版本中引入的一种新的写法,它允许开发者在函数组件中使用类似于类组件中的 state 和生命周期函数。这样可以让函数组件也具有和类组件类似的能力,使得代码更简洁易读。

例如, 下面是使用 Hooks 写的一个 InputField 组件,这个组件能够在用户输入时显示实时输入的内容:

import { useState } from 'react';

function InputField() {
  const [inputValue, setInputValue] = useState('');

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={event => setInputValue(event.target.value)}
      />
      <p>{inputValue}</p>
    </div>
  );
}

  • useState 是 React 提供的一个 Hook,它接受一个初始值作为参数,并返回一个数组,数组的第一个元素是当前状态,第二个元素是一个函数,用于更新状态。
  • 在 JSX 中,我们可以通过设置 input 的 value 属性和 onChange 事件来控制输入框的值和变化。

另外,React Hooks 还提供了一些其它的 Hooks,例如 useEffect, useContext, useReducer 等,它们可以帮助我们解决组件之间通信、副作用管理、上下文管理等问题。

例如,下面是使用 useEffect 实现组件的副作用(例如请求数据):

import { useState, useEffect } from 'react';

function DataLoader({url}) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(url)
      .then(response => response.json())
      .then(data => setData(data))
  }, [url]);

  return (
    <div>
      {data ? <p>{data}</p> : <p>Loading...</p>}
    </div>
  );
}
  • useEffect 是 React 提供的另一个 Hook,它允许我们在组件的生命周期中执行副作用,例如请求数据、订阅事件等。
  • useEffect 的第一个参数是一个函数,它会在组件挂载和更新时执行。
  • useEffect 的第二个参数是一个数组,它指定了哪些状态或属性的更改会触发 useEffect 的执行。

通过使用React Hooks,我们可以更加简洁的编写组件,并且使用Hooks的方式进行组件的状态管理和副作用管理,使得代码更加简洁易读。但是它的使用也有一些限制,例如不能在类组件中使用,也不能在循环或条件语句中使用。

总之,React Hooks 是 React 为了简化函数组件的开发而提供的一种新写法,它可以让函数组件也具有类似于类组件的 state 和生命周期函数的能力,从而提高代码的可维护性和可读性。

React的实现

  1. JSX不符合JS标准语法: React采用了JSX语法, 这种语法并不符合标准的JS语法,所以需要使用Babel将JSX转换为JS。

    Babel通过使用转换插件来完成转换的过程。在React中,通常使用babel-preset-react插件来转换JSX语法。这个插件会识别所有以React.createElement<jsx>开头的语句,并将其转换为能在浏览器上执行的JavaScript语法。

  2. 返回的JSX发生改变时,如何更新DOM: React采用了虚拟DOM技术,当JSX发生改变时,React会在内存中重新构建虚拟DOM,然后与上一个版本的虚拟DOM进行对比,找出最小的变化,最后只更新需要更新的部分。

  3. State/Props更新时,要重新触发render函数: React采用了响应式编程,当组件的state/props发生改变时,会触发重新渲染。

例如:

import React, { useState } from 'react';

function Example() {
    const [count, setCount] = useState(0);

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
        </div>
    );
}

这个例子使用了React Hooks, 在组件中使用useState hook来管理状态。它接受一个初始值作为参数,返回一个当前值和一个更新值的函数。点击按钮时,会调用setCount函数来更新状态,从而触发重新渲染。

React状态管理库

image.png

React状态管理库有很多种,其中最常用的是Redux。

Redux的核心思想是将应用中所有的状态都存放在一个全局的store中,通过派发action来更新store中的状态,我将在实例部分做一个Redux管理状态的简单示例。

应用级框架科普

image.png

三、实践练习例子:

1.下面是一个使用Redux管理状态的简单示例:

首先,我们需要安装redux库:

npm install --save redux

然后定义初始状态和reducer函数:

const initialState = { count: 0 };

function reducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

定义store:

import { createStore } from 'redux';

const store = createStore(reducer);

在组件中使用store:

import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';

function Counter() {
  const count = useSelector(state => state.count);
  const dispatch = useDispatch();

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
    </div>
  );
}

这样就完成了使用Redux管理状态的示例。当然,在实际项目中,还可以使用中间件和异步操作等高级功能。

2.在React项目中使用ESLint、Prettier和Stylelint来维护代码质量和统一代码风格。

  1. 安装ESLint、Prettier和Stylelint工具:在项目中通过npm或yarn安装这三个工具。
  2. 配置ESLint: 在项目根目录下创建一个.eslintrc.js文件,并在文件中配置ESLint的规则。
  3. 配置Prettier: 在项目根目录下创建一个.prettierrc文件,并在文件中配置Prettier的规则。
  4. 配置Stylelint: 在项目根目录下创建一个.stylelintrc文件,并在文件中配置Stylelint的规则。
  5. 配置VSCode: 使用VSCode的插件ESLint、Prettier和Stylelint,这些插件可以帮助我们在编写代码时实时监测代码质量和统一代码风格。
  6. 运行检查:使用命令行在项目根目录下运行ESLint、Prettier和Stylelint工具,检查项目中的代码是否符合规则。

通过使用这些工具可以使得代码风格统一,提高代码可读性,减少代码错误,提高项目的整体质量。

四、课后个人总结:

本节课我们学习了React相关知识,包括UI编程痛点、响应式与转换式、响应式编程、组件化、状态归属问题、生命周期等。其中,React的设计思路在于通过组件化和响应式编程来解决编写复杂UI时的痛点。我们学习了React hooks的写法,并了解到React是如何通过JSX语法和Babel来解决JSX不符合JS标准语法、如何更新DOM和如何重新触发render函数的问题。

我们还学习了React状态管理库,了解了Redux和Mobx等库的使用方法。我们还学习了react的应用级框架Next.js等。

总体来说,这节课对我的帮助很大,但是对于一些细节还需要加深理解。例如,对于状态管理库的使用,我觉得还需要多做练习才能熟练掌握。另外,对于Next.js等框架,我觉得也需要多做研究才能更好地理解。

五、引用参考:

React 的历史与应用

React 的设计思路

React (hooks)的写法与 React 实现

React 状态管理库与应用级框架科普