面试了 200 个前端后总结的 2024 前端知识图谱与学习路线

406 阅读24分钟

最近为团队简历筛选、面试了 200 多个候选人,我似乎找到了 Offer 密码

  • 学历,这个无需多言,本科普通的同学考个比较好的研究生最起码简历不会被筛了
  • 大厂工作经历,学历好 + 有大厂工作经历的同学简历筛选稳稳能通过,而且普遍解决的问题会有一定的深度,所以无论职业生涯起步最好在大厂,技术视野广一些
  • 能打的项目经历,很多同学吐槽面八股,但大部分面试官的第一选择是根据简历上写的内容展开,如果做的事情实在是简单,只能面八股,因此简历上项目描述部分最好包含使用了什么技术 + 解决了什么问题
  • 技术博客,几乎是双非+没有大厂经历同学的最后一根救命稻草,在小厂或者应届生有深度的技术项目可遇不可求,因此必须展示一下自己的技术兴趣和深度,博客是最好的展示平台

但无论怎么说要想拿到最后的 Offer 最终还是要靠技术实力,如果还是新手入门我们一般需要知识图谱和学习路线来帮助我们登堂入室

很多刚入门的同学可能会被前端庞大的知识图谱吓到,其实没必要,知识图谱是对前端领域知识进行分类梳理,其内容一般非常全面,主要用于新手了解学习范围和后面查漏补缺的学习

新手入门到进阶反而是合理的学习路线比较重要,因为知识图谱的内容并没有学习顺序,知识之间也互相交叉,比如学习前端工程化太早会觉得特别吃力,但不学就没法理解 React、Vue 怎么跑起来的。而且我们新知识的学习通过死记硬背知识点效果是很差的,一般都是理论结合时间,边学边练效果最佳

本文结合最近的面试经历和 2024 前端技术的发展,对前端知识图谱和从小白到进阶的学习路线做一个总结,希望可以帮助大家入门前端开发、找到心仪的工作

知识图谱

工具篇

画板

基础知识篇

画板

现代 Web 开发篇

画板

前端工程化篇

画板

性能优化篇

画板

前端进阶篇

画板

学习路线设计

为了让小白可以轻松上手,学习路线会对知识图谱的内容做大量删减与交叉介绍,整个学习过程会分为几个阶段,并且每个阶段都有推荐的学习资料和建议的练习项目,降低大家的选择成本

  1. 基础知识入门,模拟一个电商网站
  2. 现代 Web 开发,用企业级标准重构网站
  3. 使用 Node.js web 框架为添加后端服务
  4. 优化网站的性能

基础知识入门

代码编辑器 VS Code

工欲善其器,必先利其器,前端开发的最佳 IDE(集成开发环境)无疑是微软的 VS Code,支持 Windows、MacOS、Linux,可以点击这里下载

在 VS Code 可以安装一些通用的拓展来方便日常开发,后续介绍其它技术栈时候也有配套的插件

  • npm Intellisense:自动补全 npm 模块名称
  • Path Intellisense:为文件路径提供自动补全功能
  • Auto Rename Tag:修改开始标签时,自动更新结束标签
  • ESLint:语法规则和代码风格检查
  • filesize:在状态栏显示文件的大小
  • Import Cost:展示 inport 的包大小
  • GitLens:增强 VS Code 中的 Git 功能,提供丰富的 Git 历史和变更信息

学习资料

HTML 和 CSS 入门

我们在浏览器上看到的页面就是由 HTML 和 CSS 展示的,HTML(超文本标记语言,HyperText Markup Language) 提供了构建网页的基本结构,CSS(层叠样式表,Cascading Style Sheets) 控制网页的外观,包括颜色、字体、间距、排版等视觉效果

再次提醒大家,开始编写网页并不需要了解完所有知识才动手,强烈建议大家一边学习,一边写代码

虽然使用视频学习效率较低,但对于才开始入门的同学,视频教程可以解决很多莫名其妙的问题,大家可以先从 Bilibili 3 小时前端入门教程开始

HTML 的学习可以使用 MDN

CSS 的学习同样可以参考 MDN,CSS 的内容非常多,并且多个知识之间没有递进关系,所以我们可以从最基础的学起,掌握最基础的概念,在后面的实战中不断强化。MDN 上面知识点比较全面,可以从这个教程开始 CSS 基础,主要涉及的知识点有

  • 基础属性
  • 盒模型
  • 选择器
  • 定位
  • Flex 布局
  • 媒体查询与响应式

学习完这部分内容后我们就可以模拟一个网页了,等学完 JavaScript 后再去给添加动态效果,新版的淘宝 PC 首页是一个难度适中的模仿对象

JavaScript 语法

JavaScript 在浏览器用于为网页添加交互性和动态效果,比如用户在网页点击按钮与 HTML 和 CSS 一起构成了前端开发的三大基石,在开始入门的阶段主要关注

  • ES6 基本语法(ES6 是 JavaScript 的第六个版本,目前比较通用),这部分内容看阮一峰老师的ES6 入门教程,通俗易懂称著
  • DOM 与事件:在实际开发中 DOM 操作一般由 Vue、React 等框架代劳,无需我们亲自动手,不过了解一下基础 API 还是有必要的。这部分知识可以参考现代 JavaScript 教程 的第二章节

学习资料:

  • 《JavaScript 高级程序设计》:也就是红宝书,虽然书名说高级程序设计,但书的内容讲的非常科普,特别适合新手学习,书比较厚可以在微信读书阅读电子版

强烈不建议初学者去看《JavaScript 权威指南》、《你不知道的 JavaScript》这两本书一个适合做字典(貌似现在网络发达并不需要了),一个适合有一定基础后再读

这部分完成之后我们可以给上面写的静态 demo 加上动态效果了

git 与 github 备份代码

Git 是一个强大的版本控制工具,用于管理代码的变化和历史记录,可在本地和远程使用。GitHub 是 Git 的在线平台,增强了代码托管和协作功能,使得团队能够更有效地共享和管理项目。两者常常一起使用,开发者在本地使用 Git 来管理代码,并将代码推送到 GitHub 进行托管和协作。

快在 github 注册一个账号,保存下自己的代码,记录自己学习、成长的过程

现代 Web 开发,用企业级标准重构网站

学会代码调试

Debug(代码调试)是指在软件开发过程中,识别、分析和修复代码中的错误或缺陷(通常称为“bug”)的过程,很多时候我们并不能从错误的结果上看出来程序错在哪里,这时候需要学习一些断点调试、单步调试等程序调试技巧,快速定位程序问题

npm 与 package.json

现代前端项目使用 package.json 描述项目信息,一般 package.json 文件在相聚根目录下,文件包含几个重要的字段

  1. 必需字段:
    • name:项目的名称,通常是小写的字符串
    • version:项目的版本号,遵循语义化版本控制(Semantic Versioning)格式
  2. 描述字段:
    • description:项目的简短描述
    • main:指定模块的入口文件,通常是 index.js
  3. 作者和许可证:
    • author:项目的作者信息
    • license:许可证类型,如 MIT、Apache-2.0 等
  4. 依赖项(dependencies 和 devDependencies):
    • dependencies:列出项目的生产依赖,用户运行项目所需的包
    • devDependencies:列出开发依赖,仅在开发过程中需要的包(如测试工具、构建工具等)
  5. 脚本(scripts):可以定义自定义命令,简化常用任务的执行,例如:
"scripts": {
    "start": "node server.js",
    "test": "jest"
}

而 package.json 中的 dependencies 和 devDependencies 是由 npm 安装,npm(Node Package Manager)是 Node.js 的包管理工具,广泛用于 JavaScript 和前端开发中。它允许开发者轻松地安装、管理和分享开源代码(包),提高了开发效率和代码重用性

官网下载安装 Node.js 后会自动安装 npm,可以看看这个教程学习 npm 的基本使用,这样就可以开始前端工程化的学习了

当然业界也有 yarn、pnpm 等包管理工具,提供了和 npm 类似的功能,在后续项目实践中可以慢慢了解,对于入门了解 npm 足矣

了解前端工程化

前端工程化是指通过一系列工具、流程和最佳实践,优化和提升前端开发、构建和维护的效率与质量。

前端工程化始于代码构建,很多同学可能会好奇 JavaScript、CSS 的源码可以直接被浏览器解释执行,那么为什么经常会听到前端代码需要构建?简单总结来讲前端构建代码是为了性能、兼容性等代码优化。有了编译环节,开发时候可以用最新的语法或 TypeScript、JSX等,不用关心浏览器兼容、可执行问题

前端工程化是现代 Web 开发的基础设施,正如前面知识图谱展示的,前端工程化的知识面特别的广泛,对于初学者可以先从 脚手架 + Webpack + Babel + PostCss 开始,后面随着项目的深入会逐渐了解里面的更多细节,所以还是提醒大家一下,才开始上手不用学完

  • Webpack:模块打包工具,用于将多个资源(如 JavaScript、CSS、图像等)打包成一个静态资源
  • Babel:JavaScript 编译器, 把最新的 JavaScript 特性,自动将其转换为向后兼容的版本,从而支持更广泛的浏览器
  • PostCSS:CSS 处理工具,通过使用插件的方式扩展 CSS 的功能,支持自动添加前缀、优化和变换 CSS 代码

使用上述工具加上各种插件、loader 等就可以运行现代前端项目了,但一个个添加起来特别麻烦,因此就诞生了脚手架工具,一键初始化项目文件结构 & 工具配置,比较常用的有 React 社区的 Create React App 和 Vue 社区的 Vite

学习资料:

使用 React / Vue

React 和 Vue 是两个非常流行的前端框架,各有优势

  • React:背靠 Facebook、Vercel(Next.js 母公司),为前端带来了 JSX、DOM diff、同构等多个先进理念,社区非常活跃,国内外多个大公司使用
  • Vue:上手成本低,官方提供了各种问题标准解决方案,选择成本低

React 和 Vue 有一个共同点就是官方教程做的特别好,强烈建议大家按照广发教程先学一遍,再去看其它资料。很多时候面试应届生我问的都是官方教程中的内容,但遗憾的是多个声称熟悉 React/Vue 的同学反而回答的不能令人满意,面试结果直接遗憾的不通过

React

Vue

  • Vue 官方文档
  • Element Plus:Vue UI 组件库
  • Pinia 符合直觉的 Vue.js 状态管理库
  • Vue Router:路由管理
  • Vite:轻量级的、速度极快的构建工具,同时也取代了 vue-cli
  • Vue Element Admin:基于 Element UI 的后台管理系统模板,提供了多种常用功能和灵活的布局,适合快速构建管理应用

因为 React/Vue 几乎是现代 Web 开发的基础,网上教程非常多,对于初学者完成官网教程最重要

CSS 解决方案

随着前端工程的复杂度上升,出现了多种 CSS 解决方案,目前并没有哪个位面向未来解决方案的定论,可以根据项目具体使用有选择的学习

预处理器

CSS 预处理器是为了解决 CSS 嵌套、变量命名、函数支持等诞生的 CSS 解决方案,典型的有 LessSass,随着 CSS 原生支持变量、嵌套等,两者的使用原来越少,不过因为存在大量历史项目,可以了解一下其变量定义和嵌套的基础语法

CSS Module

CSS Modules 是一种用于 CSS 作用域隔离和模块化的方法,通过自动生成全局唯一的类名,解决 CSS全局命名空间污染问题,使样式在组件之间不会发生冲突。

CSS Modules 既不是一种规范也不是一个 library,而是一种通过构建工具实现将 CSS 文件中的类名和标识符特殊处理的方法

可以通过这里简单学习 CSS Module

CSS-in-JS

传统的前端开发将样式定义在独立的 CSS 文件中,而 CSS-in-JS 是一种使用 JavaScript 来编写 CSS 的一种模式,样式与组件逻辑一起定义,样式可以与组件的状态、 props 等动态变化,从而避免了全局样式的冲突

import React from 'react';
import styled from 'styled-components';

const Button = styled.button`
  background: ${props => props.primary ? 'palevioletred' : 'white'};
  color: ${props => props.primary ? 'white' : 'palevioletred'};
  padding: 1em;
  border: none;
  border-radius: 3px;
`;

const App = () => (
  <div>
    <Button primary>Primary Button</Button>
    <Button>Default Button</Button>
  </div>
);

export default App;

可以通过这里或者这里简单学习 CSS-in-JS

原子化 CSS

原子化 CSS 将样式细分为单一功能的原子类(atomic class),也就是说,每个 CSS 类都只实现一个特定的样式。通过组合这些小的类,开发者可以灵活地构建复杂的组件,从而实现高效和可重用的样式管理。业界最流行的就是 TailwindCSS

figure class="bg-slate-100 rounded-xl dark:bg-slate-800">
  <img class="w-24 h-24" src="/sarah-dayan.jpg" alt="" width="384" height="512">
  <div class="pt-6 space-y-4">
    <blockquote>
      <p class="text-lg">
        “Tailwind CSS is the only framework that I've seen scale
        on large teams. It’s easy to customize, adapts to any design,
        and the build size is tiny.”
      </p>
    </blockquote>
  </div>
</figure>

学习 TailwindCSS 别忘了安装官方推荐的插件 Tailwind CSS IntelliSense,可以自动提示各种各样的

TypeScript

因为 JavaScript 高度灵活,在复杂的项目中很容易出现各种类型错误,TypeScript 是一种使 JavaScript 更加安全和强大的语言,适合用于中大型项目的开发。当然浏览器不能直接运行 TypeScript 需要通过 Babel 等工具编译为 JavaScript 后运行

  • TypeScript 的学习可以使用阮一峰老师的 TypeScript 教程
  • TypeScript 提供的在线 playground 是一个在线编程环境,实时编写、运行 TypeScript 代码,非常适合于学习 TypeScript、实验新的语法和测试代码片段

使用 Node.js web 框架为添加后端服务

几乎所有的中高级前端招聘要求至少了解一门后端语言,这是因为平时前端的大部分工作需要和后端同学配合完成,HTTP 协议也是不区分前后端的,了解一门后端语言可以帮我们更好的设计技术方案,和后端配合更丝滑,Node.js 使用 JavaScript 作为语法,无疑是前端同学了解后端成本最低的方案

到 2024 年 Node.js 在前端工程化、CLI 工具、自动化脚本、桌面程序开发、静态网站生成等多个领域都在发挥作用,而在最开始 Node.js 正是为了解决现代 Web 应用在处理并发请求时的性能和可扩展性问题而诞生的,在很长一段时间内 Node.js 官方的示例代码也是 Web 服务器

// server.mjs
import { createServer } from 'node:http';
const server = createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World!\n');
});
// starts a simple http server locally on port 3000
server.listen(3000, '127.0.0.1', () => {
  console.log('Listening on 127.0.0.1:3000');
});

在 Node.js 生态系统中,有多个流行的 Web 框架可以用来构建后端服务,比较流行的有

Express

Express 是一个快速、开放、极简的 Node.js Web 应用程序框架,它是构建 RESTful APIs 和 Web 应用的基础框架。Express 对 Web 处理大部分中间件做了集成,开箱可用,因此非常是适合人项目、公司内网项目的快速启动

Koa

Koa 是由 Express 的原作者创建的下一个 Web 框架,旨在成为一个更小、更富表现力和更强大的基础框架

  • 现代化:采用了 async/await 语法,使得编写中间件和处理请求更加简洁和直观。
  • 小而精:核心库很小,提供了最基本的功能,开发者可以根据需要自由选择中间件。
  • 更好的错误处理:提供了更优雅的错误处理机制。

Koa 适合构建需要高度自定义和灵活性的 Web 应用,很多 Node.js Web 框架正是基于 Koa 做的开发,因此我们大部分时候不需要直接使用 Koa,后面介绍的三个 Web 框架可能在项目用的会比较多

也不知道为什么这三个框架要把名字起的这么像。。。

Nest.js

Nest.js 是一个构建高效、可扩展的 Node.js 服务器端应用的框架,尤其适用于构建复杂的企业级应用。

  • Nest.js 支持 TypeScript,并结合了面向对象编程、函数式编程和函数响应式编程
  • Nest.js 底层默认使用 Express,可以通过配置从而使用 Fastify
  • Nest.js 集成了许多现代工具和库,如 TypeORM、GraphQL 和 WebSocket 等,开箱可用

可以根据这篇教程入门 Nest.js

Next.js

Next.js 是一个 React 应用的框架,支持服务器端渲染(SSR)、静态生成和客户端渲染

  • 全栈能力:可以在服务器端和客户端使用 JavaScript,支持动态路由和 API 路由。
  • 优化性能:自动代码分割、静态优化和预取功能,提高性能。
  • SEO 友好:支持服务器端渲染,便于优化搜索引擎的索引。

Next.js 适合构建动态、SEO 友好的 React 应用和网站

Nuxt.js

Nuxt.js 是一个基于 Vue.js 的全栈框架,支持服务器端渲染、静态网站生成和单页应用开发

  • 模块化:支持模块化编程,使得构建和扩展应用更加便捷
  • 自动路由生成:基于文件结构自动生成路由,简化了开发过程
  • 灵活性:支持多种渲染模式(SSR、SSG 和 SPA)

适合构建高性能、SEO 友好的 Vue.js 应用和网站

优化网站的性能

说到性能优化前端同学肯定对雅虎军规特别熟悉,虽然随着网络技术的发展有些规则已经不合时宜,但其核心思想仍然在指导大部分 Web 开发者对页面进行性能优化

  • 尽快建连(使用 CDN、预加载、减少 DNS 查询等)
  • 减少传输内容
  • 复用缓存
  • 静态资源加载顺序调优
  • JavaScript、CSS 语法层面的一些优化

基础优化工作完成后性能优化进入深水区,我们需要对页面加载的去哪过程逐段拆解,一个网页的加载大概有下图过程

性能优化没有统一的答案,但有本书《前端性能揭秘》里面介绍了很多思路值得学习,Web 性能优化专栏里面的文章也可以参考

另外在开始做 Web 性能优化之前最好了解一下 HTTP 协议,《图解 HTTP》是一本不错的入门书

性能衡量指标

想要从 0 到 1 打造极致性能的 Web 页面,首先需要了解如何衡量页面的性能,什么样的页面算是性能优秀,笔者所在的团队经历过好几个阶段的探索,比如页面 TTFB、主接口达到时间、页面第一个图片被渲染时间等,总会出现指标上很快,但人的体感并不快的情况
这次我们来了解一下 Google 定义的一套以人为本的性能衡量指标—— Core Web Vitals,也被简称为 CWV,Core Web Vitals 主要关注四个性能指标:

  1. FCP:First Content Paint,首次内容绘制指标测量页面从开始加载到页面内容的任何部分在屏幕上完成渲染的时间。对于该指标内容指的是文本、图像(包括背景图像)、元素或非白色的元素
  2. LCP:Largest Content Paint,最大内容绘制指标会根据页面首次开始加载的时间点来报告可视区域内可见的最大图像或文本块完成渲染的相对时间
  3. CLS:Cumulative Layout Shift,累计布局偏移指标是测量整个页面生命周期内发生的所有意外布局偏移中最大一连串的布局偏移分数(简单理解就是页面是否有布局不稳定导致的抖动)
  4. INP:Interaction to Next Paint,下次绘制交互指标观察用户与页面进行的所有交互的延迟,并报告所有(或几乎所有)延迟中的最大值,低 INP 意味着页面始终能够快速响应绝大多数用户交互,INP 已在 2024 年 3 月取代首次输入延迟 (FID),防止页面只是首次相应用户操作快,后续加载延迟高

Core Web Vitals 专注于直接影响用户体验的性能指标,而不仅仅是技术指标。这意味着这些指标是基于用户在浏览网页时的实际感受,而非单纯的载入时间或网络速度等数据,因此上面才说这是一套以人为本的性能衡量指标

webpack 静态资源优化

这部分属于纯前端的工作,webpack 性能优化包括构建速度性能优化和打包结果页面性能优化,后者主要策略有

  • 提出无用代码,减少构建体积
  • 提取公共依赖,多脚本复用
  • 首屏静态资源分离,异步加载
  • 文件添加哈希,浏览器缓存复用

可以参考这篇文档学习

理解 CDN

静态资源加载优化

预加载与懒加载

流式渲染

流式渲染(Streaming Rendering)是指在服务器上生成页面内容时,逐步将已准备好的部分内容立刻发送到客户端,而不是等待页面所有内容全部生成才开始发送,使客户端可以更快的接收数据渲染页面,而不必等待整个页面的内容完全下载,从而实现快速的页面加载和用户可视化体验。这个过程像是水管中的水一样流动起来源源不断,因此被称为流式渲染

流式渲染实际上一个非常古老的技术,早在 HTTP 1.1 规范中就已经引入了 Transfer-Encoding: chunked 头字段,允许服务器将响应内容分批返回给客户端。服务器可以在生成响应内容的同时,将其分成小块,逐步传输给客户端,而不是等待所有内容生成完成后再返回

在浏览器端,早期的浏览器(如 Netscape Navigator 和 IE)就已经支持对部分 HTML 内容进行解析和执行。当浏览器接收到服务器返回的部分 HTML 内容时,它可以立即开始解析和执行该内容,而不需要等待所有内容加载完成

const http = require('http');

http
  .createServer((req, res) => {
    res.writeHead(200, {
      'Content-Type': 'text/html',
      'Transfer-Encoding': 'chunked',
    });
    function renderChunk(chunk) {
      res.write(`<div>${chunk}</div>`);
    }

    renderChunk('Loading...');

    setTimeout(() => {
      renderChunk('Chunk 1');
    }, 1000);

    setTimeout(() => {
      renderChunk('Chunk 2');
    }, 2000);

    setTimeout(() => {
      renderChunk('Chunk 3');
    }, 3000);

    setTimeout(() => {
      renderChunk('done!');
      res.write('</body></html>');
      res.end();
    }, 4000);
  })
  .listen(3000, () => {
    console.log('Server listening on port 3000');
  });

SSR 与同构

但随着对 JavaScript 的依赖增强, JavaScript 脚本的体积日益膨胀, 页面首次加载时用户需要等待 JavaScript 被下载和执行,这可能导致首屏渲染时间较长;同时搜索引擎爬虫在处理 CSR 应用时可能出现无法正确的抓取动态生成内容,因此 CSR 应用的 SEO 效果可能不佳

于是可以把 SSR 的首屏内容直出、SEO 友好和 CSR 流畅的用户操作体验结合起来的同构(Isomorphic)技术应运而生。同构是指在客户端和服务器端可以共享相同的 JavaScript 代码,在服务器上使用 JavaScript 渲染 HTML,然后在客户端加载该 HTML,并在客户端继续使用 JavaScript 处理交互,这样页面首次渲染通过 SSR 提供更快的首屏体验,而后续交互则通过客户端渲染,提高了应用的响应性

同构应用主要有三个步骤

  1. 初始渲染: 服务器通过 Node.js 运行 JavaScript,生成 HTML 内容并发送到客户端,用户可以快速看到页面内容
  2. 下载 JavaScript: 在客户端浏览器下载并执行 JavaScript 文件
  3. 绑定事件: 客户端的 JavaScript 会将事件监听器等功能绑定到已渲染的 HTML 元素上,使其变得可交互

服务端返回的 HTML 虽然已经让用户看到其内容,但仍然是静态 HTML,无法响应用户的交互,如同干燥的土壤,而在客户端为 DOM 绑定事件使其可交互如同未干燥的土壤补充水分,使其可以生机勃勃,这个过程有一个非常形象的专业术语——Hydration(注水),使静态的服务器渲染内容变得动态和可交互,让页面具有了“生气”

Hydration 的过程不是简单把服务器渲染的内容在客户端重新渲染,这样会造成页面内容的闪烁。ReactDOM.hydrate 会遍历这些在服务端生成的 HTML 以确保它们与客户端的 React 组件的输出一致

  • 如果内容一致,React 会使用现有 DOM,并且不会重新渲染该部分
  • 如果不一致,React 会重新渲染那些不一致的部分

一旦 Hydration 完成,React 就会将事件处理函数(如点击事件、输入事件等)绑定到这些组件上,使得内容变得可交互

import React from 'eact';
import ReactDOM from 'eact-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(<App />);

很多同学把 SSR 等同于同构是不准确的,同构相当于加强版的 SSR

  • SSR 强调的是如何在服务器上生成页面内容,同构是强调共享代码和用户体验在服务器与客户端之间的无缝转变
  • SSR 的关注点更多是如何有效生成初次页面,同构应用不仅关注初始渲染,更重视如何让页面在客户端变得动态和可交互,提供更好的性能和用户体验

结束语

并不需要掌握文章中的所有知识,才能开始投递简历找工作,实际上理解了学习路线中的前两部分后就会对要学什么、去哪里找学习资源有了清楚的认知,因此学习路线的后半部分视频教程才变得越来越少,需要大家根据自己的学习情况去选择,本文只能做到帮大家减少选择成本

在路上的你,加油!