区块链技术博客
www.b2bchain.cn

步入现代化求职学习资料

本文介绍了步入现代化求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

在上一节我们学会了通过网络请求(fetch)获取数据,并通过操纵 DOM (一个个的 HTML 节点)将数据渲染到网页中。操纵 DOM 的这种方式虽然直观,但对于复杂逻辑会变得很麻烦。曾经大名鼎鼎的 jQuery 就是因为封装了各种 DOM 的操作让写复杂逻辑变得简单而在前端世界独占鳌头,但它如今也已退出江湖。

步入现代化

jQuery

为什么呢?因为现在我们有了更好的选择,相比于直接操作 DOM 它会让界面渲染和逻辑操作代码更加简单。如果上一节直接用原生 API 操纵 DOM 的方式是刀耕火种的时代,那么使用 jQuery 就是使用灶台来做饭,而今天我们一起进入现代化厨房,看看如何更优雅地做一道菜,哦不,写一个网站。

数据驱动界面

也许你已经猜到了我今天会给你介绍 React、Vue 或者 Svelte 这几个框架,没错儿,不过在此之前,我要先给大家介绍一下它们背后相似的理念——数据驱动界面

还记得我们上节课认识的新朋友 JSON 吗?可以把它看作一种数据结构或者说数据模型,虽然这么说不太准确。数据和界面之间,其实有一个映射关系。比如下图,左边是我设计的个人卡片(很丑我知道,不过这不重要),右边是对应的 JSON,可以看见右侧的数据和左侧的界面是一一对应的(注意因为使用了 Auto layout 图层的顺序和视觉顺序相反)。

步入现代化

数据和界面的映射

于是有人就想到:我是不是可以仅仅维护一套数据,由这套数据去渲染界面,当我想要改变界面中的元素时直接改变数据就好了,不再需要去操纵 DOM 元素。比如,当我想让上面卡片中的名字变为「李可爱」,只需要改变 JSON 里面的 name 就可以了,卡片会根据新的数据重新渲染。

这就是 React 和 Vue 这些现代化框架的一个核心理念——数据驱动界面。对比起来,Vue 提供了更多的内置工具可以帮我们快速编写界面,学起来更容易上手;而 React 提供了一套更加抽象的概念,上手比较难,但我觉得从思考方式上更加直观。所以,我今天以 React 为例,带领大家重新实现一个 React 版本的个人网站,当你学完理解之后再去学习 Vue 或者 Svelte,都会很容易。

脚手架

不同于上一节我们直接创建 html、js 和 css 文件,React 的写法不能被浏览器直接解析,所以我们需要安装脚手架,来把我们编写的 React 代码编译为浏览器可以理解的代码。脚手架也是现代化前端项目必备的工具,简单来说分为两部分:

  • 包管理(Package manager):管理公用的第三方代码模块,避免重复造轮子;
  • 模块打包器(Module bundler):负责将各种代码打包在一起变为浏览器可以理解的 js 代码。

包管理(Package manager)

想象一下,你负责的前端项目正在做一个登录注册功能,你需要实现手机号或邮箱格式检测,在用户输入的格式不正确时提醒用户。对于手机邮箱格式检查这种代码,你可以亲力亲为自己实现,但有一个更好的办法是使用别人已经实现的代码模块,也就是不要重复造轮子,直接借用别人的轮子,因为还有更加重要的业务需求在等着你。

前端的包管理工具就是帮我们“借轮子”的。想象一下,在云端有一个公共的代码池,来自全球各地的工程师把自己写的代码库发布上去,每个人都可以搜索并下载自己需要的,实现尽可能多的代码复用,而不用重复造轮子。而且,当你使用的某个第三方库更新了新版本时,你还能及时更新你自己项目中的版本,保证你使用了最新的代码。

比如下图,Chris O’Hara 和 Anthony Nandaa 发布了一个叫做 validator 的代码库,坐在电脑前的你就可以直接下载下来放到自己的项目中用来检测手机邮箱格式,而不需要自己实现。这个别人写好的库加入到你的项目中就叫做项目依赖。

步入现代化

包管理工具

这个云端代码池就是 npmjs.com(Node Package Manager),而我们想要下载或发布代码库主要使用 npm 或 yarn,它们都是命令行工具,推荐使用 yarn。

看 npm 这个名字你可能会好奇为什么不叫 jpm(JavaScript package manager)?让我来稍作解释,这里的 Node 其实指的是 Node.js。JavaScript 一开始被创建只是用来实现一些基本的网页特效,虽然到后来我们可以用 JavaScript 在浏览器中做很多事情(比如定位、录音、处理图像等),但它的施展空间永远是浏览器内,很多系统级的事情它都不能做,比如说直接读取某个文件夹内的文件列表。

所以后来有人创造了 Node.js,它和 JavaScript 语法一致,只不过它不再运行于浏览器内,而是在系统中运行,能做更多系统级的事情。而后 npm 便应运而生,帮助广大的程序员来共享 Node.js 模块。现在 Node.js 更多地应用于服务端,而 JavaScript 用于客户端,但是有一些代码既可以在服务端又可以在客户端运行(比如上述的 Validator),所以慢慢地 npm 上既有 Node.js 库也有 JavaScript 库,还有这种既可用于服务端又可用于客户端的库(同构 JavaScript)。

模块打包器(Module bundler)

很久之前 JavaScript 是没有模块化的概念的,也就是你只能在 HTML 里面引入一个又一个的 <script> 标签,如果某个 js 代码文件引用了另一个 js 代码文件中的变量还需要注意前后顺序。这在网页富交互时代是很痛苦的,所以我们需要能够模块化的代码,这样在写复杂项目时才会条理比较清晰。

步入现代化

JavaScript 模块化(来自 Webpack 官网)

模块打包器就是做这件事情的。现在比较火的模块打包器是 Webpack,还有一些后起之秀比如 parcel、rollup 以及 Figma CTO 写的编译速度快得吓人的 esbuild。在这一节我们使用 Webpack 来帮我们编译处理 React 代码。

搭建项目环境

好了,现在假设你已经知道包管理模块打包器是怎么一回事了(不知道也没事,继续往后看),我们还差一步,那就是搭建运行环境(Runtime environment)。所谓的运行环境,就是程序运行所需要的系统环境。比如说我们上一些写的代码,JavaScript 为什么可以运行,就是因为浏览器给它提供了运行环境。

安装 Node.js

这一节我们需要的脚手架是直接运行在系统中的,它是用 Node.js 编译代码处理文件,所以我们需要的是一个 Node.js 运行环境。

我们可以直接去 Node.js 官网下载并安装,就有了 Node.js 运行环境。一般我们选择左边的长期支持版,它和上一节提到的 Git 一样属于命令行软件,没有 GUI。

步入现代化

下载安装 Node.js

安装好了 Node.js 我们可以在终端执行 node -v 来验证一下,输出了版本号就说明安装成功。其实 Node.js 里面也包含了 npm,所以当我们执行 npm -v 时也可以看到 npm 的版本号。

步入现代化

检测是否安装好

安装 yarn

前面推荐大家安装包管理工具 yarn来替代 npm,根据其安装文档我们可以执行 npm install -g yarn 来安装它(我们用 npm 安装了 yarn,没想到 yarn 是用来取代 npm 的,悲伤的故事)。安装完成后,在终端输入 yarn -v 如果你看到输出了版本号就说明安装成功了。

步入现代化

检测 yarn 是否安装

初始化项目

现在我们基本的工具都有了,现在可以撸起袖子开始写项目啦。先在上次项目旁边新建一个文件夹,我习惯使用命令行来创建。我把上节课的文件夹 my-portfolio 移到了个人目录下的 Projects 文件夹下,所以进入终端后我依次执行了如下命令:

  • cd Projects/code-to-design:进入 Projects 下面的 code-to-design 文件夹
  • mkdir react-portfolio:在这个文件夹下创建一个 react-portfolio 文件夹,mkdir 的意思是 make directory。
  • cd react-portfolio:进入 react-portfolio 文件夹

步入现代化

在终端进行操作

需要注意的是,你的文件目录和我的不一样,你不用按照我这个步骤来。你可以在你喜欢的地方创建文件夹,也可以不用命令直接在 Finder 中可视化地创建文件夹,但是最后一定要用终端正确地进入这个新创建的文件夹。

接着,使用 VSCode 打开我们刚刚创建的文件夹,并在里面创建一个 README.md 文件,在里面写上这个项目的介绍,你可以随便写,只要支持 Markdown 语法。

步入现代化

README.md

现在,我们打开 VSCode 的自带终端,可以依次点击顶部菜单栏的查看 -> 终端,也可以点击底部的错误警告提示区。

步入现代化

打开终端

VSCode 终端打开后默认目录就是我们当前打开的目录——react-portfolio。如果终端当前所处目录不对,执行命令可能会造成一些无法预期的后果,所以当我们不确定终端当前所处的位置时,可以执行 ls 来查看当前目录下面的文件列表来确认一下。如下,执行 ls 后终端会列出我们刚才创建的 README.md

步入现代化

ls 确认一下

接着我们在终端输入 yarn init 来初始化项目,这个命令会交互式地创建一个 package.json 文件,这个文件里面记录着这个项目的一些信息,比如作者名、GitHub 仓库地址、所需要的依赖(第三方代码依赖)等。

上述的交互式创建,就是说在你回车后需要你回答几个问题,比如项目名(name,默认是文件夹名)、版本(version)等等,都有默认值,如果你想改就直接输入再回车,不想改就直接回车,走到最后一步就会在当前目录下出现一个 package.json 文件,里面记录着你刚才填写的信息。

步入现代化

package.json

安装依赖

安装 react-scripts

现在,我们就拥有了第一个现代化前端项目,但它目前还是空空的。现在我们需要安装一些依赖来构建一个 React 运行环境。如前文所述,我们还需要一个模块打包器 Webpack 来编译打包 React 代码为浏览器可读代码,但是 Webpack 太复杂了,需要各种配置项才可以运行,我们可以使用 Fackbook 出的 Create React App 来简化这个过程。

Create React App 是一个非常完整的脚手架,他可以直接帮我们从零创建一个 React 项目,它的工作原理是把 Webpack 封装成一个代码库——react-scripts——让我们不用接触 Webpack 就可以拥有一个 React 运行的环境。

步入现代化

react-scripts 原理示意

现在我们开始安装 react-scripts。在终端输入 yarn add react-scripts -D,就会自动下载这个依赖到当前项目的 node_modules 文件夹下。我们通过 yarn 安装的所有第三方依赖都会被装在这个文件夹下,所以一般不需要去动这个文件夹。这个命令中最后的 -D 意思是这个依赖属于开发依赖,也就是它只是用来辅助我们开发的,它的代码最终并不会出现在我们项目的代码中。

步入现代化

安装依赖

安装需要一点时间,完成后我们可以看到 package.json 中多了几行:

"devDependencies": {     "react-scripts": "^4.0.3" }

我们通过 yarn 安装的依赖会被自动记录在 package.json 文件中,因为 react-scripts 是开发依赖所以它会被记在 devDependencies 下。

安装 react 和 react-dom

接下来我们的主角登场,我们需要安装 react 和 react-dom。这里需要安装两个依赖是因为 React 不止用于 Web 端(比如 React native 用于移动端开发),react 是一个核心库,而 react-dom 是用于处理 DOM 的(一般是 Web 端)。

在终端执行 yarn add react react-dom,这一次没带小尾巴 -D 是因为它俩不是开发依赖,最终要打包进我们的项目代码的。安装完成后,package.json 里面又会多几行,dependencies 表示它们是项目依赖,和上面的开发依赖区分开。

步入现代化

安装 react 和 react-dom

编写项目代码

终于可以写项目代码了,但是我们的 HTML、CSS 和 JS 文件应该放在哪呢?Create React App 的文件结构是有规定的。首先我们需要创建一个 public 文件夹并在里面放一个 index.html 文件,它里面的代码不多:

<!DOCTYPE html> <html>   <head>     <meta charset="UTF-8">     <title>Hello world</title>     <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">   </head>   <body>     <div id="root"></div>   </body> </html>

里面只有一个 ID 为 rootdiv,这就是我们后面所有代码的容器。然后我们需要创建一个 src 文件夹,并在里面创建两个文件,index.jsApp.js,文件内容如下:

// src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js';  ReactDOM.render(   <App />,   document.getElementById('root') );
// src/App.js import React, { Component } from 'react'  class App extends Component {   render () {     return (       <div>Hello world.</div>     )   } }  export default App

上面就是 React 的代码,它其实就是 js 文件,不同的是我们可以在里面写 HTML 标签。可能初次看到这种写法难以接受,但是正是这种写法让 React 变得特别灵活,且听我一一道来。

React 是怎么工作的?

这里需要简单说明一下 React 的工作原理,它不需要我们直接在 HTML 里面写页面结构,而是所有的 HTML 结构都通过 js 生成,最终挂载到容器(<div id="root"></div>)中,这也是为什么上述 React 代码都是以 .js 结尾。

React 有它自己的一套算法,可以在数据变动时使用最小开销通过 js 来改变 DOM 结构,实现页面更新。

index.js

index.js 是入口文件,它的主要作用就是把编译出来的 React DOM 结构挂载到 public/index.html 里的容器里面。

模块导入导出(Module)

前三行都是导入依赖模块,这里简单介绍一下 JavaScript 的模块化写法。如前文所述,很久之前 JavaScript 是没有模块化的,直到 2015 年 ES6(ECMAScript 第 6 版)标准中才出现了模块的语法。

使用模块的导入导出,我们可以将代码拆分为结构清晰的小模块,使其易于管理维护。比如,我们可以像下面这样写一个模块:

// add.js function add (a, b) {   return a + b }  export default add

其中的 export default add 就是将这个函数导出。接着,我们就可以在另一个文件中导入并调用它:

// another.js import addFunc from './add'  const amount = addFunc (9, 6) console.log(amount) // 输出 15

其中 import …… from '……' 的写法就是导入模块,import 后面是导入后的常量名,你可以和导出的名字一致也可以不一致;from 后面是导入的文件路径,一般根据实际情况填写相对路径,不过对于通过包管理安装的依赖不需要路径只需要名字,比如 index.js 文件中的前两行,分别导入了 reactreact-dom

一个模块文件除了可以导出默认项,还能导出很多个其他常量。比如在上述 add.js 文件中我们再导出一个常数 Pi

在上一节我们学会了通过网络请求(fetch)获取数据,并通过操纵 DOM (一个个的 HTML 节点)将数据渲染到网页中。操纵 DOM 的这种方式虽然直观,但对于复杂逻辑会变得很麻烦。曾经大名鼎鼎的 jQuery 就是因为封装了各种 DOM 的操作让写复杂逻辑变得简单而在前端世界独占鳌头,但它如今也已退出江湖。

步入现代化

jQuery

为什么呢?因为现在我们有了更好的选择,相比于直接操作 DOM 它会让界面渲染和逻辑操作代码更加简单。如果上一节直接用原生 API 操纵 DOM 的方式是刀耕火种的时代,那么使用 jQuery 就是使用灶台来做饭,而今天我们一起进入现代化厨房,看看如何更优雅地做一道菜,哦不,写一个网站。

数据驱动界面

也许你已经猜到了我今天会给你介绍 React、Vue 或者 Svelte 这几个框架,没错儿,不过在此之前,我要先给大家介绍一下它们背后相似的理念——数据驱动界面

还记得我们上节课认识的新朋友 JSON 吗?可以把它看作一种数据结构或者说数据模型,虽然这么说不太准确。数据和界面之间,其实有一个映射关系。比如下图,左边是我设计的个人卡片(很丑我知道,不过这不重要),右边是对应的 JSON,可以看见右侧的数据和左侧的界面是一一对应的(注意因为使用了 Auto layout 图层的顺序和视觉顺序相反)。

步入现代化

数据和界面的映射

于是有人就想到:我是不是可以仅仅维护一套数据,由这套数据去渲染界面,当我想要改变界面中的元素时直接改变数据就好了,不再需要去操纵 DOM 元素。比如,当我想让上面卡片中的名字变为「李可爱」,只需要改变 JSON 里面的 name 就可以了,卡片会根据新的数据重新渲染。

这就是 React 和 Vue 这些现代化框架的一个核心理念——数据驱动界面。对比起来,Vue 提供了更多的内置工具可以帮我们快速编写界面,学起来更容易上手;而 React 提供了一套更加抽象的概念,上手比较难,但我觉得从思考方式上更加直观。所以,我今天以 React 为例,带领大家重新实现一个 React 版本的个人网站,当你学完理解之后再去学习 Vue 或者 Svelte,都会很容易。

脚手架

不同于上一节我们直接创建 html、js 和 css 文件,React 的写法不能被浏览器直接解析,所以我们需要安装脚手架,来把我们编写的 React 代码编译为浏览器可以理解的代码。脚手架也是现代化前端项目必备的工具,简单来说分为两部分:

  • 包管理(Package manager):管理公用的第三方代码模块,避免重复造轮子;
  • 模块打包器(Module bundler):负责将各种代码打包在一起变为浏览器可以理解的 js 代码。

包管理(Package manager)

想象一下,你负责的前端项目正在做一个登录注册功能,你需要实现手机号或邮箱格式检测,在用户输入的格式不正确时提醒用户。对于手机邮箱格式检查这种代码,你可以亲力亲为自己实现,但有一个更好的办法是使用别人已经实现的代码模块,也就是不要重复造轮子,直接借用别人的轮子,因为还有更加重要的业务需求在等着你。

前端的包管理工具就是帮我们“借轮子”的。想象一下,在云端有一个公共的代码池,来自全球各地的工程师把自己写的代码库发布上去,每个人都可以搜索并下载自己需要的,实现尽可能多的代码复用,而不用重复造轮子。而且,当你使用的某个第三方库更新了新版本时,你还能及时更新你自己项目中的版本,保证你使用了最新的代码。

比如下图,Chris O’Hara 和 Anthony Nandaa 发布了一个叫做 validator 的代码库,坐在电脑前的你就可以直接下载下来放到自己的项目中用来检测手机邮箱格式,而不需要自己实现。这个别人写好的库加入到你的项目中就叫做项目依赖。

步入现代化

包管理工具

这个云端代码池就是 npmjs.com(Node Package Manager),而我们想要下载或发布代码库主要使用 npm 或 yarn,它们都是命令行工具,推荐使用 yarn。

看 npm 这个名字你可能会好奇为什么不叫 jpm(JavaScript package manager)?让我来稍作解释,这里的 Node 其实指的是 Node.js。JavaScript 一开始被创建只是用来实现一些基本的网页特效,虽然到后来我们可以用 JavaScript 在浏览器中做很多事情(比如定位、录音、处理图像等),但它的施展空间永远是浏览器内,很多系统级的事情它都不能做,比如说直接读取某个文件夹内的文件列表。

所以后来有人创造了 Node.js,它和 JavaScript 语法一致,只不过它不再运行于浏览器内,而是在系统中运行,能做更多系统级的事情。而后 npm 便应运而生,帮助广大的程序员来共享 Node.js 模块。现在 Node.js 更多地应用于服务端,而 JavaScript 用于客户端,但是有一些代码既可以在服务端又可以在客户端运行(比如上述的 Validator),所以慢慢地 npm 上既有 Node.js 库也有 JavaScript 库,还有这种既可用于服务端又可用于客户端的库(同构 JavaScript)。

模块打包器(Module bundler)

很久之前 JavaScript 是没有模块化的概念的,也就是你只能在 HTML 里面引入一个又一个的 <script> 标签,如果某个 js 代码文件引用了另一个 js 代码文件中的变量还需要注意前后顺序。这在网页富交互时代是很痛苦的,所以我们需要能够模块化的代码,这样在写复杂项目时才会条理比较清晰。

步入现代化

JavaScript 模块化(来自 Webpack 官网)

模块打包器就是做这件事情的。现在比较火的模块打包器是 Webpack,还有一些后起之秀比如 parcel、rollup 以及 Figma CTO 写的编译速度快得吓人的 esbuild。在这一节我们使用 Webpack 来帮我们编译处理 React 代码。

搭建项目环境

好了,现在假设你已经知道包管理模块打包器是怎么一回事了(不知道也没事,继续往后看),我们还差一步,那就是搭建运行环境(Runtime environment)。所谓的运行环境,就是程序运行所需要的系统环境。比如说我们上一些写的代码,JavaScript 为什么可以运行,就是因为浏览器给它提供了运行环境。

安装 Node.js

这一节我们需要的脚手架是直接运行在系统中的,它是用 Node.js 编译代码处理文件,所以我们需要的是一个 Node.js 运行环境。

我们可以直接去 Node.js 官网下载并安装,就有了 Node.js 运行环境。一般我们选择左边的长期支持版,它和上一节提到的 Git 一样属于命令行软件,没有 GUI。

步入现代化

下载安装 Node.js

安装好了 Node.js 我们可以在终端执行 node -v 来验证一下,输出了版本号就说明安装成功。其实 Node.js 里面也包含了 npm,所以当我们执行 npm -v 时也可以看到 npm 的版本号。

步入现代化

检测是否安装好

安装 yarn

前面推荐大家安装包管理工具 yarn来替代 npm,根据其安装文档我们可以执行 npm install -g yarn 来安装它(我们用 npm 安装了 yarn,没想到 yarn 是用来取代 npm 的,悲伤的故事)。安装完成后,在终端输入 yarn -v 如果你看到输出了版本号就说明安装成功了。

步入现代化

检测 yarn 是否安装

初始化项目

现在我们基本的工具都有了,现在可以撸起袖子开始写项目啦。先在上次项目旁边新建一个文件夹,我习惯使用命令行来创建。我把上节课的文件夹 my-portfolio 移到了个人目录下的 Projects 文件夹下,所以进入终端后我依次执行了如下命令:

  • cd Projects/code-to-design:进入 Projects 下面的 code-to-design 文件夹
  • mkdir react-portfolio:在这个文件夹下创建一个 react-portfolio 文件夹,mkdir 的意思是 make directory。
  • cd react-portfolio:进入 react-portfolio 文件夹

步入现代化

在终端进行操作

需要注意的是,你的文件目录和我的不一样,你不用按照我这个步骤来。你可以在你喜欢的地方创建文件夹,也可以不用命令直接在 Finder 中可视化地创建文件夹,但是最后一定要用终端正确地进入这个新创建的文件夹。

接着,使用 VSCode 打开我们刚刚创建的文件夹,并在里面创建一个 README.md 文件,在里面写上这个项目的介绍,你可以随便写,只要支持 Markdown 语法。

步入现代化

README.md

现在,我们打开 VSCode 的自带终端,可以依次点击顶部菜单栏的查看 -> 终端,也可以点击底部的错误警告提示区。

步入现代化

打开终端

VSCode 终端打开后默认目录就是我们当前打开的目录——react-portfolio。如果终端当前所处目录不对,执行命令可能会造成一些无法预期的后果,所以当我们不确定终端当前所处的位置时,可以执行 ls 来查看当前目录下面的文件列表来确认一下。如下,执行 ls 后终端会列出我们刚才创建的 README.md

步入现代化

ls 确认一下

接着我们在终端输入 yarn init 来初始化项目,这个命令会交互式地创建一个 package.json 文件,这个文件里面记录着这个项目的一些信息,比如作者名、GitHub 仓库地址、所需要的依赖(第三方代码依赖)等。

上述的交互式创建,就是说在你回车后需要你回答几个问题,比如项目名(name,默认是文件夹名)、版本(version)等等,都有默认值,如果你想改就直接输入再回车,不想改就直接回车,走到最后一步就会在当前目录下出现一个 package.json 文件,里面记录着你刚才填写的信息。

步入现代化

package.json

安装依赖

安装 react-scripts

现在,我们就拥有了第一个现代化前端项目,但它目前还是空空的。现在我们需要安装一些依赖来构建一个 React 运行环境。如前文所述,我们还需要一个模块打包器 Webpack 来编译打包 React 代码为浏览器可读代码,但是 Webpack 太复杂了,需要各种配置项才可以运行,我们可以使用 Fackbook 出的 Create React App 来简化这个过程。

Create React App 是一个非常完整的脚手架,他可以直接帮我们从零创建一个 React 项目,它的工作原理是把 Webpack 封装成一个代码库——react-scripts——让我们不用接触 Webpack 就可以拥有一个 React 运行的环境。

步入现代化

react-scripts 原理示意

现在我们开始安装 react-scripts。在终端输入 yarn add react-scripts -D,就会自动下载这个依赖到当前项目的 node_modules 文件夹下。我们通过 yarn 安装的所有第三方依赖都会被装在这个文件夹下,所以一般不需要去动这个文件夹。这个命令中最后的 -D 意思是这个依赖属于开发依赖,也就是它只是用来辅助我们开发的,它的代码最终并不会出现在我们项目的代码中。

步入现代化

安装依赖

安装需要一点时间,完成后我们可以看到 package.json 中多了几行:

"devDependencies": {     "react-scripts": "^4.0.3" }

我们通过 yarn 安装的依赖会被自动记录在 package.json 文件中,因为 react-scripts 是开发依赖所以它会被记在 devDependencies 下。

安装 react 和 react-dom

接下来我们的主角登场,我们需要安装 react 和 react-dom。这里需要安装两个依赖是因为 React 不止用于 Web 端(比如 React native 用于移动端开发),react 是一个核心库,而 react-dom 是用于处理 DOM 的(一般是 Web 端)。

在终端执行 yarn add react react-dom,这一次没带小尾巴 -D 是因为它俩不是开发依赖,最终要打包进我们的项目代码的。安装完成后,package.json 里面又会多几行,dependencies 表示它们是项目依赖,和上面的开发依赖区分开。

步入现代化

安装 react 和 react-dom

编写项目代码

终于可以写项目代码了,但是我们的 HTML、CSS 和 JS 文件应该放在哪呢?Create React App 的文件结构是有规定的。首先我们需要创建一个 public 文件夹并在里面放一个 index.html 文件,它里面的代码不多:

<!DOCTYPE html> <html>   <head>     <meta charset="UTF-8">     <title>Hello world</title>     <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">   </head>   <body>     <div id="root"></div>   </body> </html>

里面只有一个 ID 为 rootdiv,这就是我们后面所有代码的容器。然后我们需要创建一个 src 文件夹,并在里面创建两个文件,index.jsApp.js,文件内容如下:

// src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js';  ReactDOM.render(   <App />,   document.getElementById('root') );
// src/App.js import React, { Component } from 'react'  class App extends Component {   render () {     return (       <div>Hello world.</div>     )   } }  export default App

上面就是 React 的代码,它其实就是 js 文件,不同的是我们可以在里面写 HTML 标签。可能初次看到这种写法难以接受,但是正是这种写法让 React 变得特别灵活,且听我一一道来。

React 是怎么工作的?

这里需要简单说明一下 React 的工作原理,它不需要我们直接在 HTML 里面写页面结构,而是所有的 HTML 结构都通过 js 生成,最终挂载到容器(<div id="root"></div>)中,这也是为什么上述 React 代码都是以 .js 结尾。

React 有它自己的一套算法,可以在数据变动时使用最小开销通过 js 来改变 DOM 结构,实现页面更新。

index.js

index.js 是入口文件,它的主要作用就是把编译出来的 React DOM 结构挂载到 public/index.html 里的容器里面。

模块导入导出(Module)

前三行都是导入依赖模块,这里简单介绍一下 JavaScript 的模块化写法。如前文所述,很久之前 JavaScript 是没有模块化的,直到 2015 年 ES6(ECMAScript 第 6 版)标准中才出现了模块的语法。

使用模块的导入导出,我们可以将代码拆分为结构清晰的小模块,使其易于管理维护。比如,我们可以像下面这样写一个模块:

// add.js function add (a, b) {   return a + b }  export default add

其中的 export default add 就是将这个函数导出。接着,我们就可以在另一个文件中导入并调用它:

// another.js import addFunc from './add'  const amount = addFunc (9, 6) console.log(amount) // 输出 15

其中 import …… from '……' 的写法就是导入模块,import 后面是导入后的常量名,你可以和导出的名字一致也可以不一致;from 后面是导入的文件路径,一般根据实际情况填写相对路径,不过对于通过包管理安装的依赖不需要路径只需要名字,比如 index.js 文件中的前两行,分别导入了 reactreact-dom

一个模块文件除了可以导出默认项,还能导出很多个其他常量。比如在上述 add.js 文件中我们再导出一个常数 Pi

在上一节我们学会了通过网络请求(fetch)获取数据,并通过操纵 DOM (一个个的 HTML 节点)将数据渲染到网页中。操纵 DOM 的这种方式虽然直观,但对于复杂逻辑会变得很麻烦。曾经大名鼎鼎的 jQuery 就是因为封装了各种 DOM 的操作让写复杂逻辑变得简单而在前端世界独占鳌头,但它如今也已退出江湖。

步入现代化

jQuery

为什么呢?因为现在我们有了更好的选择,相比于直接操作 DOM 它会让界面渲染和逻辑操作代码更加简单。如果上一节直接用原生 API 操纵 DOM 的方式是刀耕火种的时代,那么使用 jQuery 就是使用灶台来做饭,而今天我们一起进入现代化厨房,看看如何更优雅地做一道菜,哦不,写一个网站。

数据驱动界面

也许你已经猜到了我今天会给你介绍 React、Vue 或者 Svelte 这几个框架,没错儿,不过在此之前,我要先给大家介绍一下它们背后相似的理念——数据驱动界面

还记得我们上节课认识的新朋友 JSON 吗?可以把它看作一种数据结构或者说数据模型,虽然这么说不太准确。数据和界面之间,其实有一个映射关系。比如下图,左边是我设计的个人卡片(很丑我知道,不过这不重要),右边是对应的 JSON,可以看见右侧的数据和左侧的界面是一一对应的(注意因为使用了 Auto layout 图层的顺序和视觉顺序相反)。

步入现代化

数据和界面的映射

于是有人就想到:我是不是可以仅仅维护一套数据,由这套数据去渲染界面,当我想要改变界面中的元素时直接改变数据就好了,不再需要去操纵 DOM 元素。比如,当我想让上面卡片中的名字变为「李可爱」,只需要改变 JSON 里面的 name 就可以了,卡片会根据新的数据重新渲染。

这就是 React 和 Vue 这些现代化框架的一个核心理念——数据驱动界面。对比起来,Vue 提供了更多的内置工具可以帮我们快速编写界面,学起来更容易上手;而 React 提供了一套更加抽象的概念,上手比较难,但我觉得从思考方式上更加直观。所以,我今天以 React 为例,带领大家重新实现一个 React 版本的个人网站,当你学完理解之后再去学习 Vue 或者 Svelte,都会很容易。

脚手架

不同于上一节我们直接创建 html、js 和 css 文件,React 的写法不能被浏览器直接解析,所以我们需要安装脚手架,来把我们编写的 React 代码编译为浏览器可以理解的代码。脚手架也是现代化前端项目必备的工具,简单来说分为两部分:

  • 包管理(Package manager):管理公用的第三方代码模块,避免重复造轮子;
  • 模块打包器(Module bundler):负责将各种代码打包在一起变为浏览器可以理解的 js 代码。

包管理(Package manager)

想象一下,你负责的前端项目正在做一个登录注册功能,你需要实现手机号或邮箱格式检测,在用户输入的格式不正确时提醒用户。对于手机邮箱格式检查这种代码,你可以亲力亲为自己实现,但有一个更好的办法是使用别人已经实现的代码模块,也就是不要重复造轮子,直接借用别人的轮子,因为还有更加重要的业务需求在等着你。

前端的包管理工具就是帮我们“借轮子”的。想象一下,在云端有一个公共的代码池,来自全球各地的工程师把自己写的代码库发布上去,每个人都可以搜索并下载自己需要的,实现尽可能多的代码复用,而不用重复造轮子。而且,当你使用的某个第三方库更新了新版本时,你还能及时更新你自己项目中的版本,保证你使用了最新的代码。

比如下图,Chris O’Hara 和 Anthony Nandaa 发布了一个叫做 validator 的代码库,坐在电脑前的你就可以直接下载下来放到自己的项目中用来检测手机邮箱格式,而不需要自己实现。这个别人写好的库加入到你的项目中就叫做项目依赖。

步入现代化

包管理工具

这个云端代码池就是 npmjs.com(Node Package Manager),而我们想要下载或发布代码库主要使用 npm 或 yarn,它们都是命令行工具,推荐使用 yarn。

看 npm 这个名字你可能会好奇为什么不叫 jpm(JavaScript package manager)?让我来稍作解释,这里的 Node 其实指的是 Node.js。JavaScript 一开始被创建只是用来实现一些基本的网页特效,虽然到后来我们可以用 JavaScript 在浏览器中做很多事情(比如定位、录音、处理图像等),但它的施展空间永远是浏览器内,很多系统级的事情它都不能做,比如说直接读取某个文件夹内的文件列表。

所以后来有人创造了 Node.js,它和 JavaScript 语法一致,只不过它不再运行于浏览器内,而是在系统中运行,能做更多系统级的事情。而后 npm 便应运而生,帮助广大的程序员来共享 Node.js 模块。现在 Node.js 更多地应用于服务端,而 JavaScript 用于客户端,但是有一些代码既可以在服务端又可以在客户端运行(比如上述的 Validator),所以慢慢地 npm 上既有 Node.js 库也有 JavaScript 库,还有这种既可用于服务端又可用于客户端的库(同构 JavaScript)。

模块打包器(Module bundler)

很久之前 JavaScript 是没有模块化的概念的,也就是你只能在 HTML 里面引入一个又一个的 <script> 标签,如果某个 js 代码文件引用了另一个 js 代码文件中的变量还需要注意前后顺序。这在网页富交互时代是很痛苦的,所以我们需要能够模块化的代码,这样在写复杂项目时才会条理比较清晰。

步入现代化

JavaScript 模块化(来自 Webpack 官网)

模块打包器就是做这件事情的。现在比较火的模块打包器是 Webpack,还有一些后起之秀比如 parcel、rollup 以及 Figma CTO 写的编译速度快得吓人的 esbuild。在这一节我们使用 Webpack 来帮我们编译处理 React 代码。

搭建项目环境

好了,现在假设你已经知道包管理模块打包器是怎么一回事了(不知道也没事,继续往后看),我们还差一步,那就是搭建运行环境(Runtime environment)。所谓的运行环境,就是程序运行所需要的系统环境。比如说我们上一些写的代码,JavaScript 为什么可以运行,就是因为浏览器给它提供了运行环境。

安装 Node.js

这一节我们需要的脚手架是直接运行在系统中的,它是用 Node.js 编译代码处理文件,所以我们需要的是一个 Node.js 运行环境。

我们可以直接去 Node.js 官网下载并安装,就有了 Node.js 运行环境。一般我们选择左边的长期支持版,它和上一节提到的 Git 一样属于命令行软件,没有 GUI。

步入现代化

下载安装 Node.js

安装好了 Node.js 我们可以在终端执行 node -v 来验证一下,输出了版本号就说明安装成功。其实 Node.js 里面也包含了 npm,所以当我们执行 npm -v 时也可以看到 npm 的版本号。

步入现代化

检测是否安装好

安装 yarn

前面推荐大家安装包管理工具 yarn来替代 npm,根据其安装文档我们可以执行 npm install -g yarn 来安装它(我们用 npm 安装了 yarn,没想到 yarn 是用来取代 npm 的,悲伤的故事)。安装完成后,在终端输入 yarn -v 如果你看到输出了版本号就说明安装成功了。

步入现代化

检测 yarn 是否安装

初始化项目

现在我们基本的工具都有了,现在可以撸起袖子开始写项目啦。先在上次项目旁边新建一个文件夹,我习惯使用命令行来创建。我把上节课的文件夹 my-portfolio 移到了个人目录下的 Projects 文件夹下,所以进入终端后我依次执行了如下命令:

  • cd Projects/code-to-design:进入 Projects 下面的 code-to-design 文件夹
  • mkdir react-portfolio:在这个文件夹下创建一个 react-portfolio 文件夹,mkdir 的意思是 make directory。
  • cd react-portfolio:进入 react-portfolio 文件夹

步入现代化

在终端进行操作

需要注意的是,你的文件目录和我的不一样,你不用按照我这个步骤来。你可以在你喜欢的地方创建文件夹,也可以不用命令直接在 Finder 中可视化地创建文件夹,但是最后一定要用终端正确地进入这个新创建的文件夹。

接着,使用 VSCode 打开我们刚刚创建的文件夹,并在里面创建一个 README.md 文件,在里面写上这个项目的介绍,你可以随便写,只要支持 Markdown 语法。

步入现代化

README.md

现在,我们打开 VSCode 的自带终端,可以依次点击顶部菜单栏的查看 -> 终端,也可以点击底部的错误警告提示区。

步入现代化

打开终端

VSCode 终端打开后默认目录就是我们当前打开的目录——react-portfolio。如果终端当前所处目录不对,执行命令可能会造成一些无法预期的后果,所以当我们不确定终端当前所处的位置时,可以执行 ls 来查看当前目录下面的文件列表来确认一下。如下,执行 ls 后终端会列出我们刚才创建的 README.md

步入现代化

ls 确认一下

接着我们在终端输入 yarn init 来初始化项目,这个命令会交互式地创建一个 package.json 文件,这个文件里面记录着这个项目的一些信息,比如作者名、GitHub 仓库地址、所需要的依赖(第三方代码依赖)等。

上述的交互式创建,就是说在你回车后需要你回答几个问题,比如项目名(name,默认是文件夹名)、版本(version)等等,都有默认值,如果你想改就直接输入再回车,不想改就直接回车,走到最后一步就会在当前目录下出现一个 package.json 文件,里面记录着你刚才填写的信息。

步入现代化

package.json

安装依赖

安装 react-scripts

现在,我们就拥有了第一个现代化前端项目,但它目前还是空空的。现在我们需要安装一些依赖来构建一个 React 运行环境。如前文所述,我们还需要一个模块打包器 Webpack 来编译打包 React 代码为浏览器可读代码,但是 Webpack 太复杂了,需要各种配置项才可以运行,我们可以使用 Fackbook 出的 Create React App 来简化这个过程。

Create React App 是一个非常完整的脚手架,他可以直接帮我们从零创建一个 React 项目,它的工作原理是把 Webpack 封装成一个代码库——react-scripts——让我们不用接触 Webpack 就可以拥有一个 React 运行的环境。

步入现代化

react-scripts 原理示意

现在我们开始安装 react-scripts。在终端输入 yarn add react-scripts -D,就会自动下载这个依赖到当前项目的 node_modules 文件夹下。我们通过 yarn 安装的所有第三方依赖都会被装在这个文件夹下,所以一般不需要去动这个文件夹。这个命令中最后的 -D 意思是这个依赖属于开发依赖,也就是它只是用来辅助我们开发的,它的代码最终并不会出现在我们项目的代码中。

步入现代化

安装依赖

安装需要一点时间,完成后我们可以看到 package.json 中多了几行:

"devDependencies": {     "react-scripts": "^4.0.3" }

我们通过 yarn 安装的依赖会被自动记录在 package.json 文件中,因为 react-scripts 是开发依赖所以它会被记在 devDependencies 下。

安装 react 和 react-dom

接下来我们的主角登场,我们需要安装 react 和 react-dom。这里需要安装两个依赖是因为 React 不止用于 Web 端(比如 React native 用于移动端开发),react 是一个核心库,而 react-dom 是用于处理 DOM 的(一般是 Web 端)。

在终端执行 yarn add react react-dom,这一次没带小尾巴 -D 是因为它俩不是开发依赖,最终要打包进我们的项目代码的。安装完成后,package.json 里面又会多几行,dependencies 表示它们是项目依赖,和上面的开发依赖区分开。

步入现代化

安装 react 和 react-dom

编写项目代码

终于可以写项目代码了,但是我们的 HTML、CSS 和 JS 文件应该放在哪呢?Create React App 的文件结构是有规定的。首先我们需要创建一个 public 文件夹并在里面放一个 index.html 文件,它里面的代码不多:

<!DOCTYPE html> <html>   <head>     <meta charset="UTF-8">     <title>Hello world</title>     <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">   </head>   <body>     <div id="root"></div>   </body> </html>

里面只有一个 ID 为 rootdiv,这就是我们后面所有代码的容器。然后我们需要创建一个 src 文件夹,并在里面创建两个文件,index.jsApp.js,文件内容如下:

// src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js';  ReactDOM.render(   <App />,   document.getElementById('root') );
// src/App.js import React, { Component } from 'react'  class App extends Component {   render () {     return (       <div>Hello world.</div>     )   } }  export default App

上面就是 React 的代码,它其实就是 js 文件,不同的是我们可以在里面写 HTML 标签。可能初次看到这种写法难以接受,但是正是这种写法让 React 变得特别灵活,且听我一一道来。

React 是怎么工作的?

这里需要简单说明一下 React 的工作原理,它不需要我们直接在 HTML 里面写页面结构,而是所有的 HTML 结构都通过 js 生成,最终挂载到容器(<div id="root"></div>)中,这也是为什么上述 React 代码都是以 .js 结尾。

React 有它自己的一套算法,可以在数据变动时使用最小开销通过 js 来改变 DOM 结构,实现页面更新。

index.js

index.js 是入口文件,它的主要作用就是把编译出来的 React DOM 结构挂载到 public/index.html 里的容器里面。

模块导入导出(Module)

前三行都是导入依赖模块,这里简单介绍一下 JavaScript 的模块化写法。如前文所述,很久之前 JavaScript 是没有模块化的,直到 2015 年 ES6(ECMAScript 第 6 版)标准中才出现了模块的语法。

使用模块的导入导出,我们可以将代码拆分为结构清晰的小模块,使其易于管理维护。比如,我们可以像下面这样写一个模块:

// add.js function add (a, b) {   return a + b }  export default add

其中的 export default add 就是将这个函数导出。接着,我们就可以在另一个文件中导入并调用它:

// another.js import addFunc from './add'  const amount = addFunc (9, 6) console.log(amount) // 输出 15

其中 import …… from '……' 的写法就是导入模块,import 后面是导入后的常量名,你可以和导出的名字一致也可以不一致;from 后面是导入的文件路径,一般根据实际情况填写相对路径,不过对于通过包管理安装的依赖不需要路径只需要名字,比如 index.js 文件中的前两行,分别导入了 reactreact-dom

一个模块文件除了可以导出默认项,还能导出很多个其他常量。比如在上述 add.js 文件中我们再导出一个常数 Pi

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 步入现代化求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们