从0到1吃透React 19:语法与原理深度剖析

226 阅读22分钟

React 19 简介

在当今的前端开发领域,React 已然成为了中流砥柱,众多开发者依赖它构建出交互性强、用户体验卓越的 Web 应用程序。而 React 19 的发布,更是在 React 发展历程中竖起了一座新的里程碑,它为开发者带来了一系列令人瞩目的新特性和性能优化,旨在提升开发者的生产力和用户体验。

React 19 引入了众多创新功能,从精致的并发渲染到新颖的状态处理机制,全方位地增强了性能和开发人员体验。在本文中,我们将深入探讨这些前沿的附加功能,揭开 React 19 的变革性功能,深入了解它们如何重塑动态用户界面开发的格局。无论你是经验丰富的 React 开发人员,还是刚接触该框架的新手,掌握 React 19 的新特性和底层原理,对于在现代 Web 开发中保持领先地位都至关重要。

React 19 语法知识详解

(一)基础语法回顾

在深入探讨 React 19 的新特性之前,我们先来简要回顾一下 React 的基础语法。

JSX(JavaScript XML):JSX 是一种看起来很像 XML 的 JavaScript 语法扩展,它允许我们在 JavaScript 代码中直接编写类似 HTML 的结构。通过 JSX,我们可以更加直观地描述 UI 界面,并且它在编译为 JavaScript 代码后进行了优化,执行速度更快,同时还具有类型安全的特性,在编译过程中就能发现错误。例如:

import React from'react';
const element = <h1>Hello, React!</h1>;

在上述代码中,

Hello, React!

就是一个 JSX 表达式,它最终会被 Babel 转译为 React.createElement('h1', null, 'Hello, React!')

组件定义:React 应用由组件构成,组件可以分为函数组件和类组件。函数组件是一种简洁的组件定义方式,它接收 props 作为参数,并返回一个 React 元素。例如:

import React from'react';

const MyFunctionComponent = (props) => {
  return <div>{props.message}</div>;
};

类组件则通过继承 React.Component来定义,它需要实现 render 方法来返回组件的 UI。例如:

import React, { Component } from'react';

class MyClassComponent extends Component {
  render() {
    return <div>{this.props.message}</div>;
  }
}

props 与 state:props(properties 的缩写)是组件之间传递数据的方式,它是只读的,父组件通过属性的方式将数据传递给子组件,子组件不能修改 props。而 state 则用于管理组件内部的状态,当 state 发生变化时,组件会重新渲染。例如在类组件中使用 state:

import React, { Component } from'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  increment = () => {
    this.setState((prevState) => ({
      count: prevState.count + 1
    }));
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

在函数组件中,我们可以使用 useState Hook 来管理状态:

import React, { useState } from'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount((prevCount) => prevCount + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

(二)新语法特性

  1. 新 Hooks
  • useActionState:useActionState 是 React 19 引入的新 Hook,用于处理表单 action 的状态更新。它允许你基于表单 action 的结果来更新组件状态。基本语法如下:
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);

其中,fn 是表单提交时调用的函数,它接收上一次状态作为第一个参数,接收表单数据作为后续参数,并返回新的状态;initialState 是初始状态值,可以是任何可序列化的值,在 action 首次调用后会被忽略;permalink 是可选的唯一页面 URL,用于动态内容页面(如 feeds),配合渐进式增强使用,在 JavaScript bundle 加载前提交表单时使用。返回值包含当前状态 state、表单 action formAction 和一个布尔值 isPending,用于表示是否处于 pending 状态。

例如,实现一个简单的计数器表单:

import React, { useActionState } from'react';

async function increment(previousState, formData) {
  return previousState + 1;
}

function Counter() {
  const [count, formAction, isPending] = useActionState(increment, 0);
  return (
    <form>
      <p>Count: {count}</p>
      <button formAction={formAction} disabled={isPending}>
        {isPending? 'Incrementing...' : 'Increment'}
      </button>
    </form>
  );
}

在上述代码中,当点击按钮时,会触发 increment 函数,useActionState 会根据函数的返回结果更新 count 状态,并自动处理 pending 状态,在按钮点击时禁用按钮,直到表单 action 完成。

  • useFormStatususeFormStatus 是一个专门用于获取父级表单提交状态的 Hook。它提供了表单提交过程中的详细状态信息,基本语法为:
const { pending, data, method, action } = useFormStatus();

其中,pending 是一个布尔值,用于告知表单是否在提交状态;data 包含了表单的数据,是实现了表单 FormData object;method 表示表单的请求方式,如常见的 post 和 get;action 是表单默认的 action prop,如果在写组件时设定了 action 的值,在 Hook 中可以获得。

使用限制为必须在 <form> 元素内部使用,且必须是表单的子组件,不能在表单 action 处理函数内使用。例如:

import React, { useFormStatus } from'react-dom';

function SubmitButton() {
  const { pending, data } = useFormStatus();
  return (
    <button type="submit" disabled={pending}>
      {pending? 'Submitting...' : 'Submit'}
    </button>
  );
}

function Form() {
  async function formAction(formData) {
    // 处理表单提交
  }

  return (
    <form action={formAction}>
      <input name="name" />
      <SubmitButton />
    </form>
  );
}

在这个例子中,SubmitButton 组件通过 useFormStatus 获取表单的提交状态 pending,根据状态来禁用或显示按钮文本,从而实现了在表单提交时禁用按钮,提交完成后恢复按钮可点击状态的功能。

  1. 其他新特性
  • 改进的事件处理:React 19 在事件处理方面进行了一些优化,使得事件处理更加高效和灵活。例如,在处理合成事件时,React 现在能够更好地处理事件的捕获和冒泡阶段,并且在事件委托机制上也有了进一步的改进,减少了不必要的事件绑定和内存开销。这意味着在开发过程中,我们可以更专注于业务逻辑的实现,而不用担心事件处理的性能问题。

  • 新的上下文 API:React 19 对上下文 API 进行了一些改进,使得上下文的使用更加简洁和直观。通过新的上下文 API,我们可以更方便地在组件树中传递数据,而无需通过层层传递 props 的方式。例如,在创建上下文时,可以使用更简洁的语法:

import React from'react';const MyContext = React.createContext();

在使用上下文时,子组件可以更方便地获取上下文的值:

import React, { useContext } from'react';
import { MyContext } from './MyContext';

function MyComponent() {
  const value = useContext(MyContext);
  return <div>{value}</div>;
}

这种改进不仅提高了代码的可读性,还减少了代码的冗余,使得跨组件数据传递变得更加容易。

React 19 底层框架原理

(一)核心概念解析

  1. 虚拟 DOM:虚拟 DOM 是 React 的核心概念之一,它是一种用 JavaScript 对象来模拟真实 DOM 结构的技术。在 React 中,当组件的状态或 props 发生变化时,并不会直接操作真实的 DOM,而是先创建一个新的虚拟 DOM 树,然后与之前的虚拟 DOM 树进行比较(使用 Diff 算法),找出差异部分,最后将这些差异应用到真实 DOM 上,从而实现最小化的 DOM 更新,提高性能。

在 React 19 中,虚拟 DOM 的实现和优化主要体现在以下几个方面:

  • Diff 算法优化:React 19 对 Diff 算法进行了进一步的优化,使其在比较虚拟 DOM 树时更加高效。通过减少不必要的比较和计算,能够更快地确定需要更新的部分,从而提高渲染性能。例如,在处理列表项的更新时,React 19 能够更准确地识别出哪些项发生了变化,避免了不必要的重新渲染。

  • 批量更新:React 19 在处理多个状态更新时,会将这些更新进行批量处理,等到合适的时机再一次性应用到虚拟 DOM 上,然后再同步到真实 DOM。这样可以减少不必要的重绘和回流,提高性能。例如,在一个组件中多次调用setState方法,React 19 会将这些更新合并,只进行一次 DOM 更新操作。

  1. 组件化机制:React 采用组件化的开发模式,将复杂的 UI 界面拆分成一个个独立的、可复用的组件。组件可以是函数组件或类组件,它们负责接收 props(属性)和维护自己的 state(状态),并返回一个描述 UI 的 React 元素。

组件生命周期:类组件拥有生命周期方法,这些方法在组件的不同阶段被调用,开发者可以在这些方法中执行一些特定的操作。React 19 中,组件的生命周期主要包括以下几个阶段:

  • 挂载阶段(Mounting):当组件首次被创建并插入到 DOM 中时,会依次调用constructor、render和componentDidMount方法。constructor用于初始化组件的状态和绑定事件处理函数;render方法返回一个 React 元素,描述组件的 UI 结构;componentDidMount在组件挂载到 DOM 后被调用,通常用于执行一些依赖于 DOM 的操作,如发起网络请求、添加事件监听器等。

  • 更新阶段(Updating):当组件的 props 或 state 发生变化时,会触发更新过程。首先会调用shouldComponentUpdate方法,用于判断组件是否需要更新,如果返回false,则组件不会更新;接着调用render方法生成新的虚拟 DOM 树,然后与旧的虚拟 DOM 树进行比较,最后调用componentDidUpdate方法,在组件更新完成后执行一些操作。

  • 卸载阶段(Unmounting):当组件从 DOM 中移除时,会调用componentWillUnmount方法,用于执行一些清理操作,如清除定时器、解绑事件监听器等,以避免内存泄漏。

Props 与 State 管理:props 是父组件传递给子组件的数据,它是只读的,子组件不能直接修改 props。props 的传递使得组件之间能够进行数据共享和通信。而 state 是组件内部维护的状态,它可以在组件内部被修改,并且当 state 发生变化时,会触发组件的重新渲染。在 React 19 中,使用useState Hook 可以方便地在函数组件中管理状态,使用useReducer Hook 可以更复杂地管理状态,类似于 Redux 的状态管理方式。例如:

import React, { useState } from'react';

const Counter = () => {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

在上述代码中,count是组件的状态,setCount是用于更新状态的函数。当点击按钮时,increment函数会被调用,通过setCount更新count的值,从而触发组件的重新渲染,页面上显示的计数也会相应增加。

(二)框架运行机制

  1. 渲染流程:React 19 的渲染流程可以分为两个主要阶段:初始化渲染和更新渲染。
  • 初始化渲染:当 React 应用启动时,首先会创建组件树,并生成对应的虚拟 DOM 树。React 会递归调用组件树的render方法或函数,生成一个完整的虚拟 DOM 树,每个组件都会返回一个表示 UI 的虚拟 DOM 节点。然后,React 将虚拟 DOM 树与当前页面的真实 DOM 进行比较(此时页面为空),由于页面中没有 DOM,React 会将虚拟 DOM 直接转化为真实 DOM。React 会遍历虚拟 DOM 树,使用document.createElement创建真实 DOM 节点,为每个节点设置属性(如className、id等),并递归插入子节点,最终将构建好的 DOM 树挂载到指定的容器中。

  • 更新渲染:当组件的state或props发生变化时,React 会触发组件的更新。首先,React 会调用组件的render方法或函数,生成新的虚拟 DOM 树。然后,使用 Diff 算法比较新旧虚拟 DOM 树,找出变化部分。Diff 算法主要通过以下几个步骤进行比较:类型比较,如果节点类型(如div和span)不同,React 直接移除旧节点并插入新节点;如果类型相同,比较属性和子节点;属性比较,比较新旧节点的属性,仅更新有变化的属性;子节点比较,React 使用key属性优化动态子节点的比较,如果没有key,React 按序逐一比较,可能导致多余的重建。最后,React 计算出需要的最小 DOM 操作(增、删、改、移),并批量更新 DOM,减少重绘和重排的次数。

在 React 16 及以上版本中,引入了 Fiber 架构,对渲染流程进行了优化。Fiber 将渲染工作分解为多个小任务(可中断的工作单元),实现了优先级机制,高优先级任务(如用户交互)可打断低优先级任务(如后台渲染)。在渲染阶段,构建新的 Fiber 树,比较新旧 Fiber 树,计算出需要的更新,此阶段是纯粹的计算,不会直接操作 DOM,且可中断,React 会优先处理高优先级任务;在提交阶段,将更新应用到真实 DOM,这是不可中断的过程,React 将计算出的差异(Patch)批量提交到 DOM。

  1. 事件处理机制:React 19 的事件处理机制是建立在原生 DOM 事件机制之上的,通过使用合成事件(SyntheticEvent)来处理和管理组件内部的事件。
  • 合成事件:React 使用合成事件来封装浏览器原生事件,提供了一个跨浏览器兼容的事件接口。合成事件是对原生事件的封装,它提供了一致的 API 和属性,使得事件处理在不同浏览器中表现一致。例如,在处理点击事件时,无论在哪个浏览器中,合成事件对象都具有相同的属性和方法,如event.target表示触发事件的目标元素,event.preventDefault()用于阻止事件的默认行为,event.stopPropagation()用于停止事件的传播。

  • 事件绑定:在 React 中,可以通过在 JSX 中直接将事件处理函数作为属性进行绑定。例如,在一个按钮上绑定点击事件可以这样写:Click Me,其中handleClick是一个普通的 JavaScript 函数,定义了事件被触发时要执行的操作。事件处理函数接收一个合成事件对象作为参数,可以通过该对象访问事件相关的信息。

  • 事件委托:React 中的事件委托通过将事件绑定在父级元素上,并使用冒泡机制捕获子元素的事件。这样可以方便地统一管理多个子组件的事件,避免为每个子组件都单独添加事件绑定。例如,在一个包含多个列表项的列表中,我们可以将点击事件绑定在列表的父元素上,当点击某个列表项时,事件会冒泡到父元素,然后在父元素的事件处理函数中根据event.target来判断具体点击的是哪个列表项,从而执行相应的操作。

  • 事件传播:合成事件对象提供了方法来阻止默认行为和停止事件传播。通过调用event.preventDefault()可以取消事件的默认行为,比如阻止链接的默认跳转行为;调用event.stopPropagation()可以停止事件的传播,避免事件冒泡到父级元素。需要注意的是,由于 React 使用了合成事件来封装浏览器原生事件,所以在使用事件属性时,命名需要遵循驼峰式命名规则,如onClick、onKeyDown等。

(三)新特性原理

  1. React 编译器:React 编译器是 React 19 引入的一个重要特性,它旨在通过自动优化来提高 React 应用的性能。React 编译器的工作原理是理解 JavaScript 语义和 React 的规则,自动对代码进行诸如记忆等优化,从而减少不必要的计算和渲染,提升应用的响应速度和用户体验。

在以往的 React 开发中,开发者需要手动使用useMemo、useCallback、React.memo等 API 来优化组件的渲染和状态更新,以避免不必要的重新渲染。而有了 React 编译器,这些手动优化工作将由编译器自动完成。例如,React 编译器可以自动识别哪些组件的渲染结果是可以缓存的,哪些函数的计算结果是可以复用的,从而减少重复计算和渲染。它通过分析组件的依赖关系和状态变化,自动决定何时以及如何更新组件,使得开发者无需再手动关注这些细节,代码更加简洁和高效。

目前,React 编译器已经在 Instagram 等生产环境中得到应用,并且源代码已经开源。不过需要注意的是,React 编译器目前仍处于实验阶段,尚未完全准备好用于生产环境,在使用时需要确保项目依赖的是 React 19 Beta 或更高版本,并且要谨慎考虑其在生产环境中的应用,等待其达到稳定版本后再进行大规模采用可能是一个更好的选择。

  1. 服务器组件:服务器组件是 React 19 中引入的一个全新概念,它允许在服务器端运行 React 组件。在传统的 React 开发中,组件主要运行于客户端,而服务器组件的出现改变了这种模式。

服务器组件的实现原理是通过在服务器端执行 React 组件的渲染逻辑,将渲染结果发送到客户端。从 Next.js 13 开始,所有组件默认都是服务器端组件,若想让组件在客户端运行,只需使用 “use client” 指令。在 React 19 中,服务器组件将直接融入 React 核心。

服务器组件具有以下优势:

  • SEO 优化:服务器渲染的组件能向网络爬虫提供更丰富的内容,因为在服务器端就已经完成了组件的渲染,网络爬虫可以直接获取到完整的 HTML 内容,进而提升搜索引擎排名。

  • 性能飞跃:服务器端组件能显著加快页面初始加载速度,因为在服务器端可以提前渲染好组件,减少了客户端的渲染工作量,优化了整体性能,尤其对内容密集型应用效果显著。

  • 服务器端执行:服务器端组件使得代码在服务器端执行成为可能,从而可以高效处理如 API 调用等任务,避免了在客户端进行多次网络请求,减少了数据传输量和客户端的计算压力 。在 React 中,所有组件默认是客户端组件,若需转为服务器端组件,只需在组件顶部添加 “use server” 即可,这样组件将仅在服务器端运行,不会涉及客户端。使用服务器组件时,可以在任何 React 组件中导入服务器组件,并通过 “Actions” 来执行特定任务。

实际应用与案例分析

(一)项目搭建与配置

在开始一个新的 React 19 项目时,首先需要搭建开发环境。我们可以使用 Create React App 这个官方工具来快速创建项目。确保你已经安装了 Node.js 和 npm(Node Package Manager),这是搭建 React 开发环境的基础工具。可以从 Node.js 官网下载并安装最新版本的 Node.js,安装完成后,npm 会自动安装。打开终端或命令提示符,输入以下命令来创建一个新的 React 项目:

npx create-react-app my-react-19-project

上述命令会创建一个名为my-react-19-project的新目录,并在其中生成初始的 React 项目文件。接着,进入项目目录:

cd my-react-19-project

在项目目录中,你可以看到如下的文件结构:

my-react-19-project
├── README.md
├── node_modules
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
└── src
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    ├── reportWebVitals.js
    └── setupTests.js

public目录包含了项目的公共文件,如index.html是项目的入口 HTML 文件,它提供了一个容器,React 应用将在其中渲染。src目录是项目的源代码目录,所有的 React 组件和逻辑代码都将放在这里。package.json文件记录了项目的依赖和脚本命令,通过npm install命令可以安装项目所需的依赖包,通过npm start命令可以启动开发服务器。

(二)案例展示与分析

为了更好地理解 React 19 的语法和原理在实际项目中的应用,我们来看一个简单的待办事项列表(To - Do List)案例。

  1. 功能需求:这个待办事项列表需要具备以下功能:用户可以输入新的待办事项,点击添加按钮将事项添加到列表中;列表中的每个待办事项都有一个勾选框,用户可以勾选表示事项已完成;已完成的事项会显示为灰色;用户可以删除已完成的事项。

  2. 组件设计:我们将创建三个主要组件:App组件作为应用的入口,负责管理整个待办事项列表的状态和逻辑;TodoInput组件用于用户输入新的待办事项;TodoList组件用于展示待办事项列表。

  3. 代码实现

// src/TodoInput.js
import React, { useState } from'react';

const TodoInput = ({ addTodo }) => {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (e) => {
    setInputValue(e.target.value);
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (inputValue.trim()!== '') {
      addTodo(inputValue);
      setInputValue('');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={inputValue}
        onChange={handleChange}
        placeholder="Enter a new todo"
      />
      <button type="submit">Add Todo</button>
    </form>
  );
};

export default TodoInput;

在TodoInput组件中,我们使用useState Hook 来管理输入框的值inputValue。当用户在输入框中输入内容时,handleChange函数会更新inputValue的值。当用户点击添加按钮时,handleSubmit函数会阻止表单的默认提交行为,检查输入值是否为空,如果不为空,则调用父组件传递过来的addTodo函数将新的待办事项添加到列表中,并清空输入框。

// src/TodoList.js
import React from'react';

const TodoList = ({ todos, toggleTodo, deleteTodo }) => {
  return (
    <ul>
      {todos.map((todo, index) => (
        <li
          key={index}
          style={{ textDecoration: todo.completed? 'line-through' : 'none', color: todo.completed? 'gray' : 'black' }}
        >
          <input
            type="checkbox"
            checked={todo.completed}
            onChange={() => toggleTodo(index)}
          />
          {todo.text}
          {todo.completed && <button onClick={() => deleteTodo(index)}>Delete</button>}
        </li>
      ))}
    </ul>
  );
};

export default TodoList;

在TodoList组件中,我们通过map方法遍历props.todos数组,为每个待办事项渲染一个列表项。根据todo.completed的值来设置列表项的样式,如果事项已完成,则添加删除按钮。当用户点击勾选框时,会调用toggleTodo函数来切换事项的完成状态;当用户点击删除按钮时,会调用deleteTodo函数来删除已完成的事项。

// src/App.js
import React, { useState } from'react';
import TodoInput from './TodoInput';
import TodoList from './TodoList';

const App = () => {
  const [todos, setTodos] = useState([]);

  const addTodo = (text) => {
    setTodos([...todos, { text, completed: false }]);
  };

  const toggleTodo = (index) => {
    setTodos((prevTodos) =>
      prevTodos.map((todo, i) =>
        i === index? {...todo, completed:!todo.completed } : todo
      )
    );
  };

  const deleteTodo = (index) => {
    setTodos((prevTodos) => prevTodos.filter((_, i) => i!== index));
  };

  return (
    <div>
      <h1>To - Do List</h1>
      <TodoInput addTodo={addTodo} />
      <TodoList todos={todos} toggleTodo={toggleTodo} deleteTodo={deleteTodo} />
    </div>
  );
};

export default App;

在App组件中,我们使用useState Hook 来管理待办事项列表的状态todos。addTodo函数用于向列表中添加新的待办事项,它通过展开运算符将新的待办事项添加到原有的 todos数组中。toggleTodo函数用于切换某个待办事项的完成状态,它通过map方法遍历prevTodos数组,找到需要切换状态的事项并更新其completed属性。deleteTodo函数用于删除已完成的待办事项,它通过filter方法过滤掉需要删除的事项。最后,将TodoInput和TodoList组件引入App组件中,并将相应的函数和数据传递给它们。

  1. 原理分析:在这个案例中,我们运用了 React 19 的基础语法,如组件定义、状态管理(使用useState Hook)和事件处理。通过useState Hook,我们能够方便地管理组件内部的状态,并且在状态发生变化时,React 会自动重新渲染相关组件,保证 UI 与状态的一致性。在事件处理方面,我们为表单提交、按钮点击和勾选框变化等事件绑定了相应的处理函数,通过这些函数来更新状态,从而实现了待办事项列表的各种功能。同时,虚拟 DOM 和 Diff 算法在背后发挥着作用,当状态发生变化时,React 会通过 Diff 算法比较新旧虚拟 DOM 树,只更新实际发生变化的部分,提高了性能。

总结与展望

image.png

React 19 以其丰富的语法知识和强大的底层框架原理,为前端开发带来了诸多优势。从语法层面看,新的 Hooks 如useActionState和useFormStatus等,为开发者处理表单和状态管理提供了更便捷、高效的方式,使代码结构更加清晰,逻辑更加简洁。在底层框架原理方面,虚拟 DOM 和 Diff 算法的优化,以及 Fiber 架构的引入,极大地提升了 React 应用的性能,使得应用能够更加流畅地运行,为用户提供更好的体验。

展望未来,React 有望在性能优化、新特性引入以及生态系统完善等方面继续发展。随着技术的不断进步,React 可能会进一步优化渲染机制,提升应用的加载速度和响应性能。同时,新的功能和特性也可能会不断涌现,以满足开发者日益增长的需求。在生态系统方面,React 的社区预计将继续壮大,提供更多的工具、库和资源,为开发者提供更强大的支持。

React 19 是前端开发领域的一个重要里程碑,它为开发者提供了更强大的工具和更深入的理解,帮助我们构建出更加优秀的 Web 应用程序。希望本文对 React 19 语法知识和底层框架原理的解析,能够帮助读者更好地掌握 React 19,在前端开发的道路上不断前行。