首页 > 其他分享 >Vue-CLI3-快速启动指南-全-

Vue-CLI3-快速启动指南-全-

时间:2024-05-16 12:20:03浏览次数:13  
标签:指南 vue CLI3 js webpack Vue 我们 CLI

Vue CLI3 快速启动指南(全)

原文:zh.annas-archive.org/md5/31ebad88f7990ce0d7b13055dbe49dcf

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

Vue 最初是由一个人 Evan You 发起的项目。令人惊讶的是,它已经发展到今天这个地步:成为最受欢迎的前端框架之一,与由公司支持的 React 和 Angular 竞争。

当然,这些并不是唯一的前端框架,但 Vue、React 和 Angular 这三者似乎是最受欢迎的,互联网上充斥着这些框架的比较和使用经验。比如,很常见的是看到一篇比较 Vue 和 React 的文章,或者一篇关于 Vue 比 Angular 更好的博客文章。无论这些文章是某人的观点,还是标题党,或者是事实陈述,这些说法肯定有一些真实性。

Vue 成功的原因是什么?是奉献、努力工作还是运气?可能都有一点。但 Vue 成功的另一个关键是 Evan 明显地优先考虑了为开发人员简化事情。Vue 不再是由一个人开发,但它仍然非常易于接近。社区一直保持着 Vue 从一开始就具有的要点:一个易于使用的框架,让你自由编码。

Vue CLI 就是这一成功的又一个例子。除了一个与其他现代前端框架相匹敌的命令行界面外,Vue CLI 3 还在前端 JavaScript 框架中树立了新的标准,并配备了图形用户界面(GUI)。这个界面使得设置、扩展、运行和服务一个 Vue 项目变得轻而易举。

当你将这个 GUI 的添加与成功地试图通过提供一个经过深思熟虑的设置过程来减轻工具链疲劳的尝试相结合时,你会得到一个非常强大的组合,开发人员也会因此而感到高兴。

这本书是为谁准备的

这本书是为网页开发人员和 JavaScript 开发人员准备的,他们想要更多地了解 Vue CLI 3。读者必须具备 HTML/CSS 和 JavaScript 的基本知识。基本上,读者还应该熟悉基本的操作系统工作流程,比如使用类 UNIX 命令行界面,包括 Git Bash、Windows PowerShell 或任何相关的命令行工具。

这本书深入探讨了 Vue CLI 3 的技术构建模块。这不是一本关于在 Vue 中编写应用程序的书。这更像是一本基础性的书,将帮助您了解 Vue CLI 内部工作原理。如果您从未完全确定 NPM 的工作原理以及如何正确使用它,这本书将通过 Vue CLI 3 的视角来解释。同样,我们将研究 webpack,HMR,使用单文件.vue组件,SCSS,ECMAScript,使用 Jest 进行单元测试以及使用 Cypress 进行端到端测试。

本书涵盖的内容包括:

第一章《介绍 Vue CLI 3》解释了如何使用 Vue CLI 3 以及为什么应该使用它。它涵盖了最佳实践以及使用 Vue CLI 3 会得到什么。我们将设置 Node 版本管理器和 NPM,安装 Vue CLI 3,并展示如何通过命令行或 GUI 启动新应用程序。

第二章《Vue CLI 3 中的 Webpack》带领读者回顾了过去几年 JavaScript 的发展概况,这导致了 webpack 的出现。它解释了一些背景概念:NPM 和 NPM 脚本,CommonJS,JS 和 Node.js 中的模块,以及模块捆绑器以及它们在浏览器中的使用。此外,我们介绍了 webpack 的工作原理以及如何运行它。最后,我们逐步解释了如何通过 NPM 添加 Vue 项目并使用 webpack。基本上,我们正在手动设置 Vue 工具链,以便我们可以欣赏 Vue CLI 3 自动为我们做了什么。

第三章《Vue CLI 3 中的 Babel》探讨了如何使用 Babel 以及使用它的好处。我们检查了 Vue 核心 Babel 插件的构建模块,包括Babel 7babel-loader@vue/babel-preset-app。我们还研究了使用 ES5 和 ES6 运行 webpack 的区别,并更新了我们的 webpack 配置,以便它能理解 Babel。

第四章《Vue CLI 3 中的测试》介绍了使用 Vue 插件,重点介绍了用于测试的插件。我们向 Vue 应用程序添加了 Jest 插件,使用 Jest 运行单元测试,并在 Vue CLI 3 GUI 中展示了一些额外的技术和工作流程,包括从项目任务页面运行任务以及在 GUI 中运行单元测试。我们讨论了测试驱动开发(TDD)以及使用断言,并在章节末尾概述了 Cypress。

第五章《Vue CLI 3 和路由》讨论了使用 vue-router 和 vuex 添加 Vue 项目,配置预设选项以及理解 vue-router 主题。这些包括命名路由、动态路由、使用 Vue 实例中的方法导航到路由、使用子路由以及延迟加载路由。

第六章《在 Vue CLI 3 中使用 ESlint 和 Prettier》向我们展示了 ESlint 是什么以及它的用处。我们还看了 Prettier,一个方便的代码格式化程序,可以在每次保存时格式化您的代码。我们讨论了通用的代码检查器以及它们的用途。

第七章《使用 SCSS 改进 CSS》描述了 SCSS 的基础知识,展示了它与 CSS 的不同之处以及可用的附加功能。我们使用了在第五章《Vue CLI 3 和路由》中构建的简单应用程序,并看到如何通过向应用程序添加 boostrap-vue 插件来改进其样式。在 VDOM 库中使用 SCSS 有时会令人困惑,在本章中,我们看到了一种实际的工作流选项。

第八章《在 GitHub Pages 上部署 Vue CLI 3 应用程序》解释了 Git 是什么以及如何设置它。我们讨论了一些基础知识,包括使用 Git 跟踪更改和提交应用程序中的更改。我们继续讨论了三棵树概念、分支和合并分支。我们注册了 GitHub 帐户,使用 GitHub Desktop 添加了 origin/master,并了解了如何发布本地存储库。最后,我们讨论了如何使用subtree功能在 GitHub 页面上部署 Vue 应用程序。

要充分利用本书

要充分利用本书,您应该对使用 Windows、HTML、CSS、JavaScript 的基础知识以及使用 Git Bash 等命令行工具有一定的了解。熟悉 Node、NPM 和一些基本的命令行实用程序将是有益的,但这并非强制要求。

下载示例代码文件

您可以从www.packt.com的帐户中下载本书的示例代码文件。如果您在其他地方购买了本书,您可以访问www.packt.com/support并注册,以便直接通过电子邮件接收文件。

您可以按照以下步骤下载代码文件:

  1. 登录或注册www.packt.com

  2. 选择“支持”选项卡。

  3. 单击“代码下载和勘误”。

  4. 在搜索框中输入书名,然后按照屏幕上的说明操作。

文件下载后,请确保使用最新版本解压或提取文件夹:

  • WinRAR/7-Zip for Windows

  • Zipeg/iZip/UnRarX for Mac

  • 7-Zip/PeaZip for Linux

该书的代码包也托管在 GitHub 上,网址为github.com/PacktPublishing/Vue-CLI-3-Quick-Start-Guide。如果代码有更新,将在现有的 GitHub 存储库上进行更新。

下载彩色图像

我们还提供了一个 PDF 文件,其中包含本书中使用的屏幕截图/图表的彩色图像。您可以在这里下载它:www.packtpub.com/sites/default/files/downloads/9781789950342_ColorImages.pdf

使用的约定

本书中使用了许多文本约定。

CodeInText:表示文本中的代码词,数据库表名,文件夹名,文件名,文件扩展名,路径名,虚拟 URL,用户输入和 Twitter 句柄。这是一个例子:“将下载的WebStorm-10*.dmg磁盘映像文件挂载为系统中的另一个磁盘。”

代码块设置如下:

{
  "name": "vue-from-npm",
  "version": "1.0.0",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },

当我们希望引起您对代码块的特定部分的注意时,相关行或项目将以粗体显示:

let CustomArticle = Vue.component('custom-article', {
    template: `
      <article>
        Our own custom article component!
      </article>`
  })

任何命令行输入或输出都以以下方式编写:

mkdir new-project-with-webpack && cd new-project-with-webpack

粗体:表示一个新术语,一个重要的词,或者你在屏幕上看到的词。例如,菜单或对话框中的单词会以这种方式出现在文本中。这是一个例子:“从管理面板中选择系统信息。”

警告或重要说明会以这种方式出现。提示和技巧会以这种方式出现。

第一章:介绍 Vue CLI 3

本书介绍了Vue CLI 3,并回答了诸如如何使用它,为什么使用它,最佳实践以及您将从中获得什么等问题。

在本章中,我们将看看如何在我们的系统上设置 Vue CLI 3。我们将首先检查 Vue CLI 3 是否已经可用,然后我们将看到如果我们需要进行全新安装或从先前版本进行更新的确切步骤。

然后我们将看看如何安装Node 版本管理器NVM),以及为什么这比简单安装 Node 更好。我们将看到在 VS Code 中如何轻松开始使用 Vue CLI 3,以及如何通过使用命令行来集成所有这些工具。

我们还将讨论为什么使用 Vue CLI 3 非常好,并且我们将通过从命令行和使用内置的 Vue CLI 3 UI 功能来运行默认的 Vue CLI 3 应用程序来实践这一点。

我们将在本章中涵盖以下主题:

  • 在您的系统上设置 Vue CLI 3

  • 安装 Vue CLI 3

  • 安装 VS Code

  • 使用无配置的 Vue CLI

  • 使用 Vue CLI 3 的好处

  • 通过默认工具链避免 JavaScript 疲劳

我们将从设置 Vue CLI 3 开始本章。

技术要求

我们只需要一些技术要求;它们如下:

  • Windows 安装(Windows 7 或更高版本)

  • 为 Windows 安装 NVM(安装的具体步骤在本章中描述)

  • 安装 VS Code(代码编辑器)

让我们开始在我们的系统上设置 Vue CLI 3。

在我们的系统上设置 Vue CLI 3

使用 Vue CLI 3 的常见方式是通过一个名为命令行界面CLI)的命令行应用程序,在那里我们运行我们的 Vue CLI 3 命令。另一个先决条件是在我们的计算机上安装 Node.js。

如果您在共享计算机上工作,比如在您的开发团队中,很有可能您已经具备了所有的先决条件。在这种情况下,您可以通过运行一些检查来验证您是否可以立即开始使用 Vue CLI 3。

Vue CLI 3 已经可用吗?

要快速检查您是否可以立即运行 Vue CLI 3 并跳过所有安装步骤,请在命令行应用程序中运行以下命令:

node --version

还可以使用此命令检查 Vue CLI 3:

vue -V

如果您得到任何高于 8.9 的 Node 版本(理想情况下,高于 8.11.0),您就可以开始了。显然,对于 Vue CLI,您希望得到任何高于 3.0.0 的版本。

此外,如果您的 Vue CLI 版本低于 V3,或者您想更新到最新的 Vue CLI,例如 3.3.0,只需运行此命令:

npm install @vue/cli

如果您没有安装 Node.js 或 Vue CLI 怎么办?

我们将使用nvmnvm-windows来安装 Node,然后安装 Vue CLI 3。

使用 Node 版本管理器安装 Node.js

我们应该使用推荐的 Node.js 版本是多少?此信息可在以下链接找到:cli.vuejs.org/guide/installation.html

目前,截至 2019 年初,要在 Vue CLI 中获得最佳结果,所需的 Node 的最低版本是 8.11.0+,但如果确实需要,您也可以使用 8.9。

这带我们来到另一个重要的决定:安装 NVM。

为什么要安装 NVM?

虽然不绝对需要安装 NVM 才能在系统上运行 Vue CLI 3,但出于几个原因,安装 NVM 是可取的。

首先,您永远不知道 Node 何时会推荐更新以修复安全问题,这通常意味着最好在您的计算机上安装更新。

其次,如果您需要运行除 Vue 之外的其他技术,这些其他技术可能还需要不同版本的 Node。要在系统上轻松切换这些所需的 Node 安装,您可以简单地安装 NVM。

在 Windows 上安装 NVM

您可以从此地址下载 Windows 的 NVM:

https://github.com/coreybutler/nvm-windows/releases

找到nvm-setup.zip文件,下载并从中提取nvm-setup.exe,然后按照以下安装步骤进行安装:

  1. 按下 Windows + R打开运行提示。在提示符中键入cmd

  2. 在提示符内部,按下Ctrl + Shift + Enter。这将以管理员权限运行命令提示符,这是下一步所需的。

  3. 访问nodejs.org,查看当前的长期支持LTS)版本号。例如,目前在 64 位 Windows 上,LTS 版本是 10.15.1。

  4. 要安装它,请在具有管理员权限的命令提示符中运行以下命令:

nvm install 10.15.1
  1. 命令提示符将记录以下消息:
Downloading node.js version 10.15.1 (64-bit) ...
  1. 下载完成后,我们可以使用下载的 Node 版本。我们用以下命令来做:
nvm use 10.15.1
  1. 最后,您可以通过运行以下命令来验证安装是否成功:
node --version
  1. 如果您想了解与您的 Node 安装一起提供的npm的版本,只需运行以下命令:
npm --version

接下来,我们将安装 Vue CLI 3。

安装 Vue CLI 3

我们可以使用npmyarn来安装 Vue CLI 3。由于npm与 Node.js 安装捆绑在一起,我们将使用npm

npm install -g @vue/cli --loglevel verbose

上述命令会全局安装 Vue CLI 3。这就是-g标志的作用。@vue/cli的语法是我们在 Vue CLI 3 中使用的,--loglevel verbose将记录我们安装的细节,这非常有用,特别是在较慢的连接和较慢的机器上,有时我们可能会开始怀疑我们的控制台是否冻结。使用--loglevel verbose,就会更清晰,这总是好的。

完成后,让我们通过运行此命令来双重检查安装的 Vue CLI 版本:

vue --version

以下是一些其他有用的命令,您应该在控制台中尝试:

vue -h

请注意,vue -hvue --help的别名。我使用前者是因为它更容易输入。

还要注意,您可以在每个单独的vue命令上运行-h标志,例如:

vue create -h
vue add -h
vue invoke -h
vue inspect -h
vue serve -h
vue build -h
vue ui -h
vue init -h
vue config -h
vue upgrade -h
vue info -h

运行任何上述命令将返回特定命令的用法说明,描述其功能以及要附加到每个单独命令的选项(标志)。显然,-h标志是探索 Vue CLI 功能的好方法,并且在需要时即时刷新您的记忆。

接下来,我们将安装我们选择的代码编辑器 VS Code。

安装 VS Code

要安装 VS Code,只需转到code.visualstudio.com,然后下载适合您操作系统的版本。

如果您不确定自己使用的是 32 位还是 64 位计算机,您可以通过在命令提示符(具有管理员权限)中运行以下命令来快速检查 Windows 上的情况:

wmic os get osarchitecture

输出将是OSArchitecture,在下一行,要么是32 位,要么是64 位

一旦 VS Code 被下载,只需运行下载的安装文件并按照安装说明进行安装。

安装完 VS Code 后,您将在命令行中获得一个额外的命令,code

code命令非常有用,我们将在下一节中看到。

在没有配置的情况下使用 Vue CLI

在本节中,我们将看到使用 Vue CLI 的最快最简单的方法。它完全不需要任何配置!使用 Vue CLI 无需配置的原因是为了进行一些快速实验,而不必回答关于项目配置的提示,这是 Vue CLI 在运行包含配置步骤的项目时通常会询问的(这是使用 Vue CLI 构建应用程序的默认方法)。

首先,按住Shift键,在桌面的空白区域右键单击。从弹出的上下文菜单中,单击“在此处打开命令窗口”命令。

打开后,输入以下命令:

mkdir noConfig

这将创建一个名为noConfig的新目录。接下来,让我们使用cd命令切换到该目录:

cd noConfig

最后,使用以下命令从命令提示符启动 VS Code:

code .

前面命令中的点表示在当前文件夹中打开 VS Code。可以关闭欢迎标签页。

接下来,使用Alt + F键盘快捷键打开文件菜单,并按下N键打开一个全新的文件。

在新文件中,打开标签页,输入以下代码:

<template>
  <h1>What's up, Vue CLI 3?</h1>
  <hr>
</template>

接下来,按下Ctrl + S键盘快捷键,将文件保存为App.vue

VS Code 将保存文件。它将给出一个新的图标,Vue 标志图标,这是一个视觉提示,刚刚保存的文件确实是一个 Vue 文件。

VS Code 也可能提示您安装一个名为Vetur的扩展,具体提示如下:

The 'Vetur' extension is recommended for this file type.

通过单击弹出窗口底部的安装按钮来安装扩展。

请注意,安装Vetur扩展与使用没有配置的 Vue CLI 3 无关,但与我们在 VS Code 中使用 Vue 时更加高效有关。

现在我们可以通过运行vue serve来为我们的 Vue 应用程序提供服务。但是,在实际运行命令之前,让我们使用-h标志来查看我们有哪些可用选项:

vue serve -h

这就是我们将得到的内容:

Usage: serve [options] [entry]

serve a .js or .vue file in development mode with zero config

Options:
 -o, --open Open browser
 -c, --copy Copy local url to clipboard
 -h, --help Output usage information

现在我们知道可以期待什么,让我们使用以下命令为我们的 Vue 应用程序提供服务:

vue serve -o -c

因此,正如之前提到的,这个命令将为我们的 Vue 应用程序提供服务,并在浏览器中打开它。它还将复制提供的 URL 到剪贴板。这使我们可以,例如,打开一个不同的非默认浏览器,并轻松地粘贴 URL 到浏览器的地址栏中,这样我们也可以在那里预览我们的应用程序。

然而,我们将遇到一个小问题。

我们将在命令中得到这个通知,而不是我们的 Vue 应用程序被提供服务:

Command vue serve requires a global addon to be installed.
Please run npm install -g @vue/cli-service-global and try again.

这是一个简单的修复。更好的是,我们将使用--loglevel verbose扩展前面的命令:

npm install -g @vue/cli-service-global --loglevel verbose

一段时间后,根据你的下载速度,你会收到npm info ok的消息。

这意味着你现在可以再次运行vue serve命令:

vue serve -o -c

这次它成功了!有点...

现在我们收到一个错误,上面写着编译失败,有 1 个错误。然后,更进一步地,我们看到了根本原因:

Component template should contain exactly one root element.

有几种方法可以解决这个问题,但它基本上是说我们可以将我们的h1hr标签包裹在一个div标签中,然后我们就可以了。所以,让我们在 VS Code 中更新App.vue文件为这样:

<template>
  <div>
    <h1>What's up, Vue CLI 3?</h1>
    <hr>
  </div>
</template>

确保保存你的更改,现在,最后,让我们再次提供服务:

vue serve -o -c

你可能会有点惊讶,因为一个新的标签页会自动打开,加载应用程序,显示在你的默认浏览器中。

假设你的默认浏览器是 Chrome。让我们打开另一个浏览器(例如 Firefox),点击管理栏内部,并按下Ctrl + V快捷键粘贴剪贴板的内容。当然,它将是http://localhost:8080/

通过使用-o-c标志,我们以非常简单的方式执行了打开应用程序并复制其 URL 的重复任务只是冰山一角。Vue CLI 3 还有更多功能,可以帮助我们更快更轻松地编写我们的应用程序。

例如,让我们回到我们的代码,删除带有hr标签的行,然后保存文件。看看你的浏览器标签,打开我们的 Vue 应用程序的标签。它将自动刷新,反映代码的更改。这就是 webpack 在 Vue CLI 3 的内部运行,监视我们的 Vue 文件的更改,并相应地在浏览器中热重新加载应用程序。

如果你已经编码超过几年,你会欣赏到这种工作流的便利。过去,我们要么必须设置我们的工具,使它们在我们保存文件时自动刷新浏览器中的应用程序,要么我们必须设置我们的 IDE 或代码编辑器,或者两者兼而有之。甚至直到最近,我们仍然不得不调整 webpack 来自动化这种工作流程,而且像任何与编码相关的事情一样,有时并不像我们希望的那样顺利。

使用 Vue CLI 3,所有这些都是自动化的,非常简单。

让我们看看 Vue CLI 3 如何帮助我们更好地编码并提高生产力的其他方式。

使用 Vue CLI 3 的好处

当 Vue CLI 3 推出时,Vue 的创始人 Evan You 列出了它的这些目标:

  • 通过简化设置来避免前端开发的工具链疲劳

  • 遵循工具的最佳实践

  • 使这些最佳实践成为 Vue 应用的默认设置

除了这些伟大的目标,Vue CLI 还带来了许多更新,比如以下内容:

  • 预设的 webpack 配置

  • ES2017 和 Babel 7 支持开箱即用

  • 出色的 CSS 支持,包括Sassy CSSSCSS)和PostCSS支持

  • 许多集成选项(TypeScript,PWA,Web 组件,端到端测试,Jest 等)

这是很多功能。本书的目的是遍历所有选项,并让您熟悉它们的内部工作原理。

现在,让我们来看看使用默认选项设置默认应用有多么容易,来结束本章。

默认工具链,疲劳程度为零

在本节中,我们将创建一个默认的 Vue 应用程序模板。与上一节相反,在本节中,我们将真正构建一个完整的应用程序。我们将使用两种方法:命令行上的 Vue CLI 3 和带有 GUI 的 Vue CLI 3。

您可能会问为什么我们首先没有配置运行 Vue CLI 3?答案是,这可能对快速实验和开始使用一些基本命令很有用。

通过命令行创建 Vue CLI 3 默认应用

我们使用vue create命令创建 Vue CLI 3 应用程序。让我们看看我们有哪些选项可用:

vue create -h

这就是将返回的内容:

Usage: create [options] <app-name>

create a new project powered by vue-cli-service

Options:
-p, --preset <presetName> Skip prompts and use saved or remote preset
-d, --default Skip prompts and use default preset
-i, --inlinePreset <json> Skip prompts and use inline JSON string as preset
-m, --packageManager <command> Use specified npm client when installing dependencies
-r, --registry <rul> Use specified npm registry when installing dependencies (only for npm)
-g, --git [message] Force git initialization with initial commit message
-n, --no-git Skip git initialization
-f, --force Overwrite target directory if it exists
-c, --clone Use git clone when fetching remote preset
-x, --proxy Use specified proxy when creating project
-b, --bare Scaffold project without beginner instructions
-h, --help output usage information

让我们首先跳过所有提示,使用默认选项:

vue create -d first-default-app

您的控制台将显示以下输出:

Vue CLI v3.3.0
? Creating project in C:\...
? Initializing git repository...
? Installing CLI plugins. This might take a while...

确实需要一段时间。幸运的是,有一个进度条,让我们知道我们在设置项目时进行到了哪个阶段。

准备好后,我们只需运行以下命令:

cd first-default-app

一旦我们的控制台指向正确的目录,我们可以使用以下命令运行应用:

npm run serve

现在我们可以在浏览器中查看默认应用程序:

正如我们所看到的,我们有一个欢迎消息,然后页面列出了安装的 CLI 插件。显然,babeleslint插件是默认的。每个链接都指向 GitHub 上vue-cli存储库中的各自部分。

接下来,我们看到一些基本链接和一些链接,以了解更大的Vue.js生态系统(即,vue-routervuexvue-devtoolsvue-loaderawesome-vue的链接)。

通过 UI 创建 Vue CLI 3 默认应用

要开始使用 Vue CLI GUI,让我们首先使用Ctrl + C快捷键停止在上一节中运行的服务器。控制台将会回应以下消息:

Terminate batch job (Y/N)?

输入Y(大小写不重要)并按下Enter键。

这将使我们重新获得当前控制台窗口的控制,并允许我们输入新命令。

让我们首先在控制台中从当前目录向上一级:

cd ..

接下来,让我们运行这个命令:

vue ui -h

然后我们将得到以下输出:

Usage: ui [options]

start and open the vue-cli ui

Options:
-H, --host <host> Host used for the UI server (default: localhost)
-p, --port <port> Port used for the UI server (by default search for available port)
-D, --dev Run in dev mode
--quiet Don't output starting messages
--headless Don't open browser on start and output port
-h, --help output usage information

这次,我们将不使用任何标志运行该命令:

vue ui

我们将在控制台中看到以下输出:

? Starting GUI...
? Ready on http://localhost:8000

这次,我们可以通过可视化方式创建一个项目。最初,我们看到当前文件夹中没有 Vue 项目:

让我们点击“创建”选项卡来创建一个项目。

将打开一个新窗口,有一个大按钮,上面写着在这里创建一个新项目:

正如我们在前面的截图中看到的,还有许多其他按钮和选项可以使用。我们将在接下来的章节中进行详细讨论;目前,我们只是熟悉我们正在使用的工具:

正如我们从前面的截图中看到的,页面底部的“下一步”按钮当前是禁用的。要启用它,只需在最顶部的输入框中输入项目文件夹名称。我们将文件夹命名为second-vue-project。现在点击“下一步”。

在下一个窗口中,您可以选择一个预设。让我们将其设置为默认预设:

选择一个预设将使“创建项目”按钮可点击。您将在屏幕中央看到一个加载图标,并显示以下消息:

Installing Vue CLI plugins. This might take a while...

在安装过程中,您将看到一些其他消息。最后,当完成时,您将会看到以下窗口:

我们的项目现在已经准备好进行工作了,我们将在下一章中进行。

摘要

在本章中,我们看了如何使用 Vue CLI 3 开始,既可以使用命令行,也可以使用 Vue CLI UI。

我们已经看到如何安装所有先决条件,并且我们看到了建议的工作流程和一些基本指针,以便轻松入门。由于了解如何在命令行和 UI 上使用 Vue CLI,我们现在可以轻松初始化 Vue 应用程序。我们知道在启动新项目时有哪些选项可供我们选择。然而,还有许多其他事情我们需要了解 Vue CLI 的内部工作原理。

在下一章中,我们将通过专注于 webpack 来进一步改进我们的工作流程,webpack 是 Vue CLI 3 核心的模块捆绑器。

第二章:Vue CLI 3 中的 Webpack

在上一章中,我们看到了如何通过命令行和 UI 开始使用 Vue CLI。在本章中,我们将从 Vue CLI 3 的角度介绍 webpack 的基础知识。我们将首先概述 webpack 是什么。我们将研究模块捆绑、摇树、webpack 加载器和输出、webpack 插件、热模块替换HMR)、代码覆盖和代码拆分的概念,然后我们将看看这些概念如何与 Vue CLI 3 配合,如下所示:

  • 从脚本标签到模块捆绑器的 JavaScript(JS)语言的演变

  • 脚本标签

  • 立即调用函数表达式IIFEs),它们解决了什么问题,以及它们没有解决的问题

  • Node Package Manager (NPM)如何帮助团队在他们的代码中共享第三方库

  • JS 任务运行器和 NPM 脚本的作用

  • CommonJS 规范是什么,以及它如何在 JavaScript 和 Node.js 中工作

  • 模块捆绑器是什么,以及它们如何弥合 Node.js 和浏览器之间的差距

  • webpack 是什么,以及它是如何工作的

  • 如何在项目中运行 webpack

  • 使用生产和开发模式使用 webpack 捆绑资产

  • 通过 NPM 添加 Vue 项目并使用 webpack

准确理解 webpack 的工作原理对于理解 Vue CLI 3 的魔力至关重要。如果您熟悉 webpack,您可能仍然会发现本章的某些部分有用。如果您觉得自己是 webpack 专家,您可能可以直接跳过本章。

在深入了解 webpack 是什么以及正确理解 webpack 解决的问题之前,我们需要回顾一下过去十年中 JS 语言发生的一些变化。

JS 语言的演变

从 webpack 的角度来看,以下是 JS 生态系统中添加的方法、技术、最佳实践和模式的时间顺序列表,这些方法、技术、最佳实践和模式导致了当前的状态:

  • script标签作为向网页添加交互性的答案

  • 立即调用函数表达式作为模块化库和避免代码冲突的答案

  • IIFEs 的问题

  • 使用 NPM 在团队环境中共享第三方库

  • JS 任务运行器和 NPM 脚本

  • JS 中的模块

让我们更详细地看看这些解决方案中的每一个。

脚本标签

最初,将 JS 添加到您的网页意味着您需要直接在 HTML 中添加一些script标签。对于快速原型,这仍然是一种有效的做法,甚至到今天。很多时候,第三方库是通过script标签内的src属性添加的(通常放在我们的 HTML 中关闭body标签的正上方)。

不幸的是,您通常需要在 HTML 中添加多个script标签。而不管您是直接将 JS 代码添加到页面中,还是从项目中的另一个文件添加,或者从远程位置添加(例如从内容传送网络CDN)使用src属性),最终,所有这些脚本都被添加到全局 JS 范围内。这意味着一件事,冲突。

为了避免冲突,采取了一个巧妙的方法,即使用 IIFE。

立即调用的函数表达式

IIFE 到底是什么?IIFE 简单地利用了 JS 中括号不能包含语句的事实。这个事实本身允许 JS 开发人员放入匿名函数,他们可以立即调用,而不会因为简单地将它们包装在括号中而从解析器中得到任何错误。

IIFE 本质上是 JS 语言的一个怪癖,但是非常有用;通过 IIFE,所有的代码都被限定在函数范围内,因此您的代码不会受到外部任何其他东西的影响。换句话说,使用 IIFE 是避免冲突的一种简单方法,即意外覆盖变量或函数。因此,有一段时间,许多流行的库开始将它们自己的代码包装成 IIFE。例如,如果您打开 jQuery 库的代码(code.jquery.com),或 Chart.js 库的代码(cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.js),或许多其他流行的 JS 库的代码,您会发现它们使用了 IIFE 模式。

因此,通过 IIFE,我们可以向页面添加不同的脚本,而不必担心代码冲突可能发生。

IIFE 的问题

不幸的是,仅仅使用 IIFE 并不能解决我们所有的问题。为了说明手头的问题,让我们引用 Erlang 的创始人 Joe Armstrong 的话:

“你想要香蕉,但你得到的是拿着香蕉的大猩猩,整个丛林。”

请记住,在这段引用中,阿姆斯特朗先生讨论的是面向对象语言的问题,但根本问题在 JS 代码模块化中也适用。

基本上,我们对 IIFEs 的问题在于我们无法从 JS 库中精选出我们想要使用的特定功能。使用 IIFE 模式,我们必须使用 IIFE 中包含的所有内容,即使我们只是使用特定库代码库的一小部分。当然,老实说,IIFEs 并不是这个问题的罪魁祸首。长期以来,JS 语言根本没有能力精选任何类型的代码功能,因为在 JS 中,将代码拆分成模块是不可能的。

JS 的另一个主要痛点是在团队之间重复使用第三方代码的问题。

使用 NPM 在团队环境中共享第三方库

IIFEs 解决了代码冲突的问题,但并没有解决代码重用的问题。如果我的团队中的开发人员有一个不同的、更新的库版本,其中有破坏性的更改,该怎么办?如果我决定在我的计算机上更新依赖关系,我的其他团队成员将如何处理?除了使用源代码版本控制,还有其他更快的协作选项吗?

Node Package ManagerNPM)是这些问题的答案。Node 只是一个可以在服务器上运行的 Google V8 JS 引擎。NPM 允许开发人员将新库安装到项目中,无论是用于应用程序的前端还是后端。因此,NPM 实际上是 JS 包管理器,类似于 Ruby(gems (rubygems.org/))、C#(NuGet (www.nuget.org/))或 Linux 中的apt-getyum

例如,假设我们想通过 NPM 安装 Vue。如果我们的计算机上安装了 Node,那么我们也会有 NPM,因为 NPM 随 Node 一起捆绑安装。

接下来,我们需要创建一个新目录。让我们将此目录的名称更改为vue-from-npm,并将命令行控制台指向它。然后我们可以跟随这个命令:

npm init -y

运行上述命令将创建一个package.json文件。-y标志接受控制台中提示的所有默认答案。

如果我们查看项目目录中新创建的package.json文件,我们会看到以下内容:

{
  "name": "vue-from-npm",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

请注意,npm init命令只会将package.json文件添加到空目录中。就是这样!

然后,添加 Vue 就像运行这个命令一样简单:

npm install vue --save --verbose

上述命令将执行一些操作,即:

  • 它将添加node_modules目录。

  • 它将整个 Vue 库放在node_modules目录中。

  • 它将在我们项目的根目录中创建package-lock.json文件。

  • 它将更新我们项目的根目录中的package.json文件。

更新后的package.json文件现在看起来是这样的:

{
  "name": "vue-from-npm",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "vue": "².6.7"
  }
}

如果不明显的话,文件已经更新了一个新条目:dependencies。这个条目列出了项目中包含的所有依赖项。具体来说,我们已经将 Vue(版本 2.6.7 或以上)添加到了我们的项目中。

NPM 的一个很棒的地方是,我们可以像添加 Vue 一样轻松地向我们的项目添加任何其他库。例如,要使用 accounting.js 更新我们的项目,我们只需运行这个命令:

npm install accounting-js --save --verbose

安装完成后,让我们再次检查node_modules目录:

vue-npm/node_modules/
 ├── accounting-js/
 │ ├── dist/
 │ ├── lib/
 │ ├── CHANGELOG.md
 │ ├── package.json
 │ └── README.md
 ├── is-string/
 ├── object-assign/
 └── vue/

请注意,为了简洁起见,我们只显示了accounting-js文件夹内的第二级文件夹和文件。is-stringobject-assignvue文件夹都被折叠显示。

这向我们展示了有时其他 NPM 模块会捆绑实际安装的库。在accounting-js的情况下,我们还得到了is-stringobject-assign NPM 模块。让我们也检查一下我们目录根目录中更新的package.json文件:

{
  "name": "vue-from-npm",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "accounting-js": "¹.1.1",
    "vue": "².6.7"
  }
}

正如我们所看到的,根package.json文件已经更新为正确的accounting-js版本。让我们找到另一个package.json文件,这次是在node_modules/accounting-js文件夹中。如果你打开了那个文件,它包含了更多信息,仅仅超过 100 行代码。这些信息是特定于实际的 NPM 模块accounting-js

好的,现在我们的项目已经准备好进行协作了。怎么做呢?让我们看看我们的一个同事,让我们称他为“约翰”,如何在他自己的电脑上添加我们刚刚创建的项目和所有项目依赖项。

为此,我们将创建一个新文件夹,让我们称之为johns-computer,然后我们只需将vue-from-npm文件夹中的根级package.json复制到我们的johns-computer文件夹中。

接下来,让我们简单地运行这个命令:

npm install --verbose

运行上述命令将安装我们在vue-from-npm文件夹中的所有项目和依赖项。

JavaScript 任务运行器和 NPM 脚本

大约在 NPM 变得流行的同时,另一种前端技术也在崛起:任务运行器。任务运行器是简单的工具;它们运行重复的任务。有时,任务运行器被称为构建工具,因为它们充当开发人员对代码库进行更新和最终生成的生产就绪代码之间的中介。这就是所谓的构建步骤,这是软件开发过程中的一部分,在这个过程中,你的代码在你编写完之后会发生一些事情。

例如,CSS3 中添加的新功能通常以供应商前缀(也称为浏览器前缀)的形式开始。换句话说,在新的 CSS 功能在所有浏览器中可用之前,它会在各个浏览器中以实验阶段实现,使用浏览器特定的前缀,如下所示:

-ms-
-moz-
-o-
-webkit-

在这个按字母顺序排列的浏览器前缀列表中,我们可以看到微软浏览器、Mozilla、旧版本的 Opera,最后是所有基于 webkit 的浏览器(Chrome、Safari、新版 Opera 等)的浏览器前缀。

跟踪浏览器前缀的更新是有点困难的。开发人员的时间可能不是最好的用法,去监视 CSS 实现的变化,然后相应地更新他们的代码。例如,在过去的某个时间点,有必要在 CSS 的transition属性上使用以下浏览器前缀:

-webkit-transition: background-color 1s;
-moz-transition: background-color 1s;
-o-transition: background-color 1s;
-ms-transition: background-color 1s;

显然,今天我们在 CSS 声明中简单地使用transition属性,而不需要任何浏览器前缀,因为transition属性在所有现代浏览器中得到了广泛支持。

不得不应对不断变化的 CSS 规范和各种浏览器中的实现带来的不断变化的情况,导致了任务运行器这种解决方案的出现。前端开发人员现在不再需要手动向他们的 CSS 代码中添加供应商前缀,而是可以简单地向他们的任务运行器添加一个插件,它会为他们做这些繁重的工作:在需要时添加供应商前缀。

当然,我们之前看到的只是任务运行器用于的一个例子。其他一些例子包括:压缩 CSS 和 JS 文件,从 ES6 转译为 ES5,从 SASS 编译 CSS,删除未使用的 CSS,在项目中保存文件时重新加载浏览器,等等。

今天,有许多不同的工具帮助我们有效地自动化开发过程中的一些任务。三个工具脱颖而出:Grunt、Gulp 和 NPM 脚本。

虽然 Grunt 和 Gulp 是独立的任务运行器,可以通过 NPM 安装,但基于 NPM 的脚本是一个有趣的替代方案,原因如下:

  • 您已经在使用 NPM,为什么不更熟悉一下您已经在使用的工具呢?

  • 使用 NPM 脚本而不是前面提到的任务运行器将进一步简化您的开发流程。

  • 通过使用 NPM,您可以避免使用任务运行器插件来自动化 NPM 中可以自动化的任务的复杂性。

直到这一点,我们已经回顾了 JS 生态系统的历史和演变。我们已经看到了 IIFE 如何用来处理意外的作用域泄漏。我们还看到了 NPM 如何处理代码共享。我们进一步看到了如何使用任务运行器自动化一些重复的任务,以及如何使用 NPM 来通过将任务保留在 NPM 脚本中来消除不必要的抽象层。

然而,我们还没有看到解决 JS 中代码模块化问题的方法。所以,让我们接着看看。

JavaScript 中的模块

在任何编程语言中,模块都是一个独立的功能块。您可以将它们视为电视节目的不同集数。它们可以独立查看。它们可以独立存在,尽管它们是整体的一部分。

就像电视节目中的一集有一个季节和一个编号,这样我们就知道它在更大情节中的位置一样,一个模块也包含了告诉我们它依赖的其他模块(模块依赖)以及它为整个应用程序添加了什么功能的信息;这就是所谓的模块接口,对其他模块公开的 API。

我们已经看到,在开始时,JS 根本没有模块。这在 Node.js 的引入后发生了变化。Node.js 实际上是 CommonJS 的一种实现,这是由 Mozilla 的 Kevin Dangoor 在 2009 年发起的一个项目。

CommonJS 项目的目的是定义一个标准库,提供供在浏览器之外使用的 JS API。这包括一个模块规范,这导致开发人员能够在 Node.js 中使用这样的代码:

var bootstrap = require('bootstrap');

在 Node.js 中使用模块

让我们在 Node.js 中要求并使用一些模块:

  1. 首先,我们将创建一个新目录。让我们称之为module-practice。让我们将 Git Bash 指向这个文件夹。

  2. 一旦进入其中,让我们创建两个新文件。让我们将这些文件命名为main.jswhatever.js,如下所示:

touch main.js whatever.js
  1. 接下来,让我们按照以下步骤在 VS Code 中打开整个文件夹:
code .
  1. 现在,让我们向whatever.js添加一些代码如下:
console.log('whatever');

这就是 JS 中代码的简单形式。

  1. 现在让我们看看如何使它在我们的main.js文件中可用。我们只需要像下面这样要求whatever.js
let whatever = require('./whatever');
  1. 现在它被要求了,我们可以使用它,所以让我们将main.js更新为这样:
let whatever = require('./whatever');

whatever.returnWhatever();
  1. 现在让我们用以下方式运行这段代码:
node main.js

现在会发生的是,我们将在 Git Bash 中看到单词whatever被打印出来。

让我们进一步进行我们的实验。这是我们更新后的whatever.js

module.exports = {
    returnWhatever: function() {
        console.log('whatever');
    }
}

因此,我们需要更新main.js如下:


whatever.returnWhatever();

正如我们已经看到的,require关键字导入了一个模块的代码,并使其在另一个文件中可用;在我们的例子中,就是main.js文件。

exports关键字让我们可以将代码提供给其他文件,但有一个注意事项。它还允许我们选择我们想要向其他文件提供的模块的哪些部分。正如我们所看到的,module.exports是一个对象。这个对象的内容在我们的main.js要求whatever模块时将被返回。这使我们能够仅暴露代码的某些部分,并且使模块接口的设置成为可能。换句话说,module.exports是使我们能够保持代码的部分私有的东西。考虑对whatever.js的这个更新:

module.exports = {
    returnWhatever: function() {
        returnSomething();
    }
}

let returnSomething = () => {
    console.log('whatever');
}

我们不需要对main.js进行任何更改。如果我们从 Git Bash 运行它,仍然会在控制台输出单词whatever。但是我们已经使whatever.js的部分内容不直接可访问。

作为一个旁注,注意在前面的代码中,ES3 和 ES5 的函数语法一起使用。定义returnSomething函数的代码部分使用了更新的语法,这使我们能够在不使用function关键字的情况下编写函数定义。

模块捆绑器,一种在浏览器中使用模块的方法

不幸的是,你不能直接在浏览器中使用require关键字,正如我们刚才看到的那样。require关键字不是 JS 浏览器 API 的一部分。这里需要注意的是,Node.js 有能力读取和写入计算机文件系统。因此,如果你在项目中使用 Node.js 安装了任何 NPM 包,你就可以像之前解释的那样要求这样一个模块。

然而,浏览器中的 JS 无法访问你的操作系统文件系统,因此这给我们留下了一个难题:我们如何在浏览器中使用 JS 模块语法?

答案是:我们有一个工具可以做到这一点,它被称为模块捆绑器

今天,在 2019 年,有许多不同的模块打包工具可用,比如 webpack(webpack.github.io/)、FuseBox(fuse-box.org/)、Parcel(parceljs.org/)、rollup.js(rollupjs.org/guide/en)或 Browserify(browserify.org/)。

什么是模块打包工具?以下是 Browserify 主页上的一句话,简洁地表达了它:

“Browserify 让你可以在浏览器中使用 require('modules')来捆绑所有你的依赖项。”

除了打包项目中通过模块所需的所有依赖项,模块打包工具还解决了循环依赖等问题;也就是说,它们使用算法来解析项目中所有依赖项应该在项目中捆绑的顺序。

我们几乎完成了对 JS 生态系统的概述。接下来,我们将看一种特定的模块打包工具,那就是 webpack。

一旦我们知道 webpack 究竟是什么,以及它在幕后是如何工作的,我们就能完全理解它在 Vue CLI 中的位置。

什么是 webpack?

Webpack 是 Web 的模块打包工具。有些人也把它称为 Web 应用程序的资产编译器。

根据 webpack 的 GitHub 页面:

“它将许多模块打包成少量的捆绑资产等等。模块可以是 CommonJs、AMD、ES6 模块、CSS、图片、JSON、CoffeeScript、LESS 等等,还有你自定义的东西。”

在本章的前面,标题为在 Node.js 中使用模块的部分中,我们只是浅尝辄止地介绍了模块在 Node 应用程序中的导出和引入。我们没有提到的是,我们可以使用各种不同的模块语法。正如前面提到的,Node.js 使用 CommonJS 模块语法。除了 CommonJS,还有异步模块定义AMD)。除了 AMD,你还可以使用 ESM 模块。使用 ESM 模块时,语法与我们之前看到的有些不同。

让我们按照以下步骤使用 ESM 语法重写whatever模块,并在main.js中使用它:

  1. 为了简化事情,让我们创建一个新的文件夹如下:
mkdir es6-module-practice;
  1. 让我们使用cd命令(更改目录命令)指向我们的 Git Bash 如下:
cd es6-module-practice
  1. 让我们按照以下方式添加我们的两个文件:
touch whatever2.mjs main2.mjs
  1. 现在,让我们按照以下方式打开我们的文件夹与 VS Code:
code .
  1. 接下来,让我们添加main2.mjs的代码如下:
import returnWhatever from './whatever2';

returnWhatever();
  1. 最后,让我们按照以下方式编写whatever2.mjs的代码:
let returnWhatever = () => {
    returnSomething();
}

let returnSomething = () => {
    console.log('whatever');
}

export default returnWhatever;
  1. 正如我们所看到的,我们需要将文件保存为 ESM 模块,使用mjs文件扩展名。Node.js 实验性地支持 ESM 模块,因此您需要在 Git Bash 中运行以下命令:
node --experimental-modules main2.mjs
  1. 运行上述命令后,您将在控制台中看到以下输出:
(node:12528) ExperimentalWarning: The ESM module loader is experimental.
whatever

正如我们所看到的,除了在控制台中收到预期的输出之外,我们还收到了ExperimentalWarning消息。希望这个演示两种不同模块语法的示例能帮助我们理解 webpack 将为我们做什么。除其他事项外,它将平衡竞争环境,这样我们就可以在项目中使用各种标准和非标准的模块工作方式。

基本上,webpack 所做的是,它接受具有依赖项的模块(包括我们项目的资产,如.png.jpeg.scss文件),并输出静态资产(.js.css.image文件)。

webpack 的工作原理

我们已经看到了如何使用 CommonJS 和 ESM 模块语法。再次强调,CommonJS 是 Node.js 模块使用的语法。这意味着 Node.js 模块中的所有依赖项都是使用require命令描述的。与此相反,webpack 模块的依赖项可以用各种语法描述。例如,如果您的模块依赖于一个 SCSS 部分,您将使用@import语句。如果您正在导入 AMD 模块的依赖项,您将使用其自己的requiredefine语法。

这意味着,基本上webpack 模块接受导入各种依赖项的不同语法。甚至src属性(用于img HTML 元素)也被视为 webpack 模块的依赖项。

构建一个新项目并在其上运行 webpack

现在,让我们通过以下步骤构建一个项目并将 webpack 捆绑到我们的工作流程中:

  1. 让我们添加一个新目录。让我们运行一个不存在的命令,如下所示:
new-project-with-webpack

控制台将返回以下内容:

bash: new-project-with-webpack: command not found
  1. 太棒了!现在,让我们使用重复上一条命令的快捷方式,双感叹号,如下所示:
mkdir !! && cd !!

运行上述命令将创建我们的new-project-with-webpack文件夹,并将cd进入这个新目录。双和符号命令(&&)只是一种运行多个命令的方式,而不是一个接一个地输入它们。双感叹号命令(!!)表示重复上一行,所以上述命令实际上意味着以下内容:

mkdir new-project-with-webpack && cd new-project-with-webpack
  1. 接下来,让我们添加我们的package.json,并接受所有默认值(使用-y标志)如下:
npm init -y
  1. 让我们按以下步骤检查我们在 VS Code 中的文件夹内容:
code .
  1. 一旦 VS Code 在我们的屏幕上运行,我们可以双击package.json文件并验证其内容如下:
{
  "name": "new-project-with-webpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

  1. 现在,让我们按照以下步骤将 webpack 添加到我们的项目中:
npm install --save-dev webpack webpack-cli --verbose
  1. 完成后,让我们回到 VS Code 并再次审查我们的package.json如下:
{
  "name": "new-project-with-webpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "⁴.29.5",
    "webpack-cli": "³.2.3"
  }
}

正如我们所看到的,一个新的键已经被添加:devDependencies。在其中,我们有webpackwebpack-cli开发依赖。这些devDependencies是你在构建项目时才会使用的依赖项,而 webpack 就是这样一个依赖的完美例子:你在生产环境中不需要 webpack。这就是为什么我们在通过 NPM 安装 webpack 时使用了--save-dev标志。

查看我们项目的文件结构,我们现在可以看到以下内容:

node_modules/
package.json
package-lock.json

如果你打开node_modules文件夹,你会看到里面有 300 多个文件夹。这个庞大的依赖列表以一个.bin文件夹开始。与我们之前的一个例子vue-from-npm相比,其中node_modules文件夹内只有四个子文件夹,尽管我们安装了vueaccounting-js两个 NPM 包。还要注意的是,在vue-from-npm文件夹内,没有.bin文件夹。无论你在运行npm install时使用--save还是--save-dev标志,情况都是如此。虽然这对于更有经验的开发人员可能是显而易见的,但对于那些在 Node.js 和 NPM 生态系统方面经验不足的开发人员来说,更好地理解这一点可能是很重要的。

那么,这个.bin文件夹是什么?它只是存储了你使用npm install安装的 Node 模块的编译后的本地二进制文件(即可执行文件)。并非所有的 NPM 模块都有这些编译后的本地二进制文件,这就是为什么你不会总是在node_modules文件夹内看到.bin文件夹的原因。在这个.bin文件夹内,有许多不同的 Node 模块。这些对于 webpack 正常工作都是必要的。

回到我们的项目,现在让我们向其中添加两个文件:index.jswhatever.js,如下所示:

touch index.js whatever.js

目前,我们不会向这些文件中添加任何代码。现在,我们将专注于在我们的项目中运行 webpack。

在一个项目上运行 webpack

回到我们的new-project-with-webpack文件夹,再次检查package.json的内容,重点关注scripts键如下:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
},

在 Git Bash 中使用以下命令运行test脚本:

npm run test

这将抛出一个带有exit code 1的错误。

让我们对它做一些更改,如下所示:

"scripts": {
    "test": "echo \"You haven't specified any tests\""
},

让我们再次用npm run test来运行测试。这次控制台的输出不会那么可怕,因为我们删除了exit 1命令,并且改变了运行test命令时会被回显的内容。

让我们尝试完全不同的东西,如下所示:

"scripts": {
    "test": "node index.js"
},

现在,我们不会得到错误,因为我们的index.js是空的。让我们添加一些内容,如下所示:

// add up 2 numbers
console.log(2+2)

保存对index.js的更改,再次运行npm run test,这次在 Git Bash 中的输出将会打印出数字4

这告诉我们什么?它告诉我们我们完全控制我们的脚本将要做什么!所以,最初我们有一个名为 test 的脚本。这个脚本会回显一条消息,并抛出一个带有exit code 1的错误。

就像我们可以给我们的脚本任意的键名,比如test,我们也可以给它们任意的值。当然,console.log(2+2)是一个愚蠢的值给一个脚本键。我们可以给我们的脚本键更好的值,例如:

  "scripts": {
    "webpack": "webpack"
  },

现在,当我们用 webpack 的值运行一个 NPM 脚本时,这个脚本将运行 webpack 可执行文件。让我们试一下,如下所示:

npm run webpack

这会返回一个错误,但在所有被记录下来的信息中,以下两行是最重要的:

Insufficient number of arguments or no entry found.
Alternatively, run 'webpack(-cli) --help' for usage info.

我们得到这个错误的原因是因为 webpack 在寻找入口点来启动。默认情况下,这个入口点被设置为./src/index.js。所以,让我们添加这个src文件夹,并将我们的index.js移动到其中,如下所示:

mkdir src && mv index.js $_

现在,让我们再次从命令行运行 webpack,如下所示:

npm run webpack

这次我们会得到一个更好的输出。然而,默认情况下 Git Bash 没有语法高亮。这可以很快解决。因为我们已经在使用 VS Code,只需键入Ctrl + ~的快捷键。如果你对这个符号不熟悉,它叫做tilde,位于Esc键下方,Tab键上方。按下这个快捷键将在 VS Code 中打开一个终端窗口,如果你再次执行npm run webpack命令,你会得到格式良好且带有颜色高亮的输出,就像这样:

图 2.1:在 VS Code 中将信息记录到控制台的 webpack 作为一个侧面说明,你的屏幕颜色可能会有所不同,这取决于你在 VS Code 中使用的颜色方案。要访问颜色主题,请使用以下键盘快捷键:Ctrl + K Ctrl + T

查看控制台输出的消息,我们可以看到它可以分为两部分:实际信息(哈希、版本、时间、构建时间、入口点等)和警告。警告显示我们没有设置mode选项。

如果未设置,mode选项默认为生产模式。但是,我们也可以将其设置为development,这对于更快的构建进行了优化。这意味着我们可以在package.jsonscripts部分中添加另一个脚本,然后可以用于项目的开发构建。这是更新后的scripts部分:

"scripts": {
    "webpack": "webpack",
    "dev": "webpack --mode=development"
},

现在,我们可以使用以下命令在 webpack 中运行开发模式:

npm run dev

这是控制台中的完整输出:

Hash: 86c0da41f48381d9bd70
Version: webpack 4.29.5
Time: 108ms
Built at: 2019-02-27 12:23:30
 Asset Size Chunks Chunk Names
main.js 3.81 KiB main [emitted] main
Entrypoint main = main.js
[./src/index.js] 38 bytes {main} [built]

我们可以看到,webpack 在开发模式下花了108ms来打包我的项目。当我在生产模式下运行它(在我的设置中默认的npm run webpack命令),它花了447ms

运行这个命令时实际上发生了什么?webpack 在后台做了什么?它构建了所有模块依赖的依赖图。回到本章前面的比喻,就好像我们给了它一堆电视剧的剧集,录在一堆蓝光光盘上,它把它们全部拿来并正确地排列起来。Webpack 找出了每个模块的正确位置,然后将它们捆绑起来并提供给dist文件夹。如果再次查看项目的文件结构,你会发现有一个新的添加:dist文件夹。如果我们检查dist文件夹的内容,我们会看到:

./dist/
   |- main.js

如果我们检查main.js文件,我们会看到 webpack 添加了很多东西。即使在像我们这样的小项目上,输出也会有大约 100 行长。

我们的main.js文件的前几行如下:

/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
...

让我们再次运行npm run webpack命令,看看它如何影响main.js中的输出。

如果我们检查main.js,我们会看到现在只有一行代码,以以下内容开头:

!function(e){var t={};function n(r){if(t[r])return t[r].exports;var ...

这意味着当以生产模式运行时,webpack 会对我们的代码进行混淆和缩小。

显然,这也会影响文件大小。在开发模式下,打包的main.js文件大小为 3.81 KB,而在生产模式下,它只有 944 字节。

最后,为了避免看到警告消息,我们可以将package.json中的脚本条目更新为:

"scripts": {
    "webpack": "webpack --mode=production",
    "dev": "webpack --mode=development"
},

在这一点上,我们可以开始使用 webpack 与 Vue。但是,我们不会使用 Vue CLI。相反,我们将看到如何手动设置所有内容。这不是做事情的最佳方式,但它将帮助我们更好地理解为什么在 Vue 生态系统中会这样做。

通过 NPM 添加一个 Vue 项目并使用 webpack

在这一部分,我们将使用 NPM 构建一个新项目,然后将 webpack 添加到其中,并最终添加一个 Vue 单文件组件。

首先,让我们按照以下步骤新建一个目录。我们将我们的项目命名为npm-vue-webpack

  1. 打开 Git Bash 并按照以下方式添加一个新文件夹:
mkdir npm-vue-webpack && cd $_
  1. 按照以下方式初始化npm
npm init -y
  1. 接下来,按照以下步骤将 Vue 和 webpack 安装到我们的新项目中:
npm install vue webpack webpack-cli --save-dev --verbose

一旦 NPM 安装完成,我们可以像在本章前面那样验证package.json的文件夹和内容。

  1. 接下来,按照以下方式添加我们的项目将使用的源文件夹和输出文件夹:
mkdir dist src
  1. 按照以下步骤打开我们的新项目在 VS Code 中:
code .

现在,我们可以直接从 VS Code 编辑器中添加两个新文件。我们将第一个文件命名为source.js,第二个文件命名为output.js。确保在此阶段将这两个空文件添加并保存到您的项目中:source.jssrc文件夹中,output.jsdist文件夹中。

将我们的 Vue 组件添加为 JavaScript 模块

现在让我们添加我们的 Vue 组件:

  1. 接下来,让我们按照以下方式将这段代码添加到source.js中:
import CustomArticle from './CustomArticle.js';

new Vue({
    el: '#app',
    render: h => h(CustomArticle),
})
  1. 在第一行,我们正在导入一个名为CustomArticle.js的文件。

  2. 让我们在src文件夹内新建一个文件。我们将这个文件命名为CustomArticle.js

  3. 并将以下代码添加到其中:

let CustomArticle = Vue.component('custom-article', {
    template: `
      <article>
        Our own custom article component!
      </article>`
  })

export default CustomArticle;

我们可以看到,我们正在使用 ESM 语法来导出和导入 JS 模块。

使用 webpack 编译 JavaScript 模块

现在我们几乎可以准备好使用 webpack 将我们的source.js编译为output.js了。但在这之前,我们仍然需要按照以下方式更新我们的package.json中的scripts部分:

"scripts": {
    "webpack": "webpack"
},

现在,我们可以在 Git Bash 中运行以下命令:

npm run webpack ./src/source.js ./dist/output.js

正如预期的那样,我们在控制台中看到了输出,以及关于设置模式选项的警告。我们现在知道这意味着什么,所以在这个时候处理它并不重要。

如果我们检查output.js的内容,我们会发现它是空的,并且默认情况下,webpack 会将我们的输出代码压缩和混淆到默认的main.js文件中,具体如下:

!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i ...

那么,我们如何让 webpack 输出到一个不同的文件,而不是默认的main.js?我们使用 webpack 配置文件!

通过 webpack 配置文件添加选项

使用 webpack 配置文件,我们可以添加各种选项来打包我们的应用程序。具体如下:

  1. 在项目的根目录添加一个新文件。我们将这个文件命名为webpack.config.js。代码如下:
module.exports = {
  output: {
    filename: 'output.js',
  }
};
  1. 现在,再次运行我们的命令如下:
npm run webpack ./src/source.js ./dist/output.js

这次它输出到了正确的文件。

  1. 就像我们可以指定输出文件一样,我们也可以指定输入文件如下:
module.exports = {
 entry: './src/source.js',
 output: {
 filename: 'output.js',
 }
};

我们仍然需要在屏幕上的某个位置渲染我们的 Vue 组件。我们需要一个 HTML 文件来实现这一点。

添加一个 HTML 文件,以便渲染我们的 Vue 组件

让我们在dist文件夹中添加一个新的 HTML 文件,我们将其命名为index.html,具体如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Compiled HTML file</title>
</head>
<body>
    <div id="entryPoint"></div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
    <script src="output.js"></script>
</body>
</html>

就像我们在本章开头讨论的那样,我们以老派的方式直接向 HTML 中添加脚本,只需在 HTML 文件底部堆叠script标签。我们使用的第一个script标签是从 CDN 获取 Vue,第二个script标签从dist文件夹中获取我们的output.js文件。

如果你使用 VS Code,现在可以右键单击新的dist/index.html文件,然后单击“在默认浏览器中打开”命令。

在打开的网页上会看到以下句子:

我们自己的自定义文章组件!

现在,我们需要让 webpack 能够输出 HTML 文件。为此,我们需要使用html-webpack-plugin

赋予 webpack 输出 HTML 文件的能力

在本节中,我们将看到如何使用 webpack 插件输出 HTML 文件,具体步骤如下:

  1. 通过 NPM 安装html-webpack-plugin如下:
npm install html-webpack-plugin --save-dev --verbose
  1. 我们的package.jsondevDependencies已相应更新如下:
"devDependencies": {
    "html-webpack-plugin": "³.2.0",
    "vue": "².6.7",
    "webpack": "⁴.29.5",
    "webpack-cli": "³.2.3"
}
  1. 现在,按照以下步骤更新我们的webpack.config.js
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/source.js',
    output: {
        filename: 'output.js',
    },
    plugins: [new HtmlWebpackPlugin()]
};
  1. 在继续之前,删除dist文件夹中的index.html文件。不过不用担心删除它,因为 webpack 很快就会重新创建它。

  2. 接下来,再次运行 webpack 脚本如下:

npm run webpack

Webpack 刚刚为我们创建了一个新的index.html文件!文件内容如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack App</title>
  </head>
  <body>
  <script type="text/javascript" src="output.js"></script></body>
</html>

这都很好,但显然,我们的文件不一样了。我们丢失了 Vue 组件的入口点。此外,我们需要更新我们的 Vue 代码,使其作为单文件组件工作。

将.vue 文件作为 JavaScript 模块添加

首先,让我们更新source.js文件,如下所示:

import Vue from 'vue';
import CustomArticle from './CustomArticle.vue';

new Vue({
    el: '#entryPoint',
    render: h => h(CustomArticle),
})

现在我们还可以将CustomArticle.js重命名为CustomArticle.vue,并向其中添加以下代码:

<template>
  <div id="entryPoint">
      <article>
        Our own custom article component!
      </article>
  </div>
</template>

不幸的是,webpack 不能直接处理.vue文件。为了解决目前的问题,我们需要使用webpack 加载器。webpack 加载器帮助 webpack 理解它正在处理的文件。有许多加载器,但现在我们需要使用 Vue。

添加 webpack 加载器以处理.vue 文件

要处理.vue文件,请按以下步骤进行:

  1. 通过 NPM 安装名为vue-loader的 webpack 加载器,如下所示:
npm install vue-loader --save-dev --verbose
  1. 现在我们已经保存了它,我们需要使用它,我们将通过更新 webpack 配置来做到这一点:
let HtmlWebpackPlugin = require('html-webpack-plugin');
let VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    entry: './src/source.js',
    output: {
        filename: 'output.js',
    },
    plugins: [
        new HtmlWebpackPlugin(),
        new VueLoaderPlugin(), 
    ]
};
  1. 现在尝试运行 webpack,如下所示。剧透警告:它会失败:
npm run webpack

我们得到的错误消息如下:

Error: [VueLoaderPlugin Error] No matching rule for .vue files found.
  1. 要修复此错误,我们需要为我们的 Vue 加载器添加一个规则,通过更新我们的webpack.config.js文件如下:
let HtmlWebpackPlugin = require('html-webpack-plugin');
let VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    entry: './src/source.js',
    output: {
        filename: 'output.js',
    },
    module: {
        rules: [
            { test: /\.vue$/, use: 'vue-loader' }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin(),
        new VueLoaderPlugin(), 
    ]
};

rules选项中数组内的test键接收一个正则表达式作为值。这个正则表达式检查是否存在一个带有vue文件扩展名的文件。如果匹配,也就是说,如果找到了一个vue文件,它将在其上使用vue-loader模块。

  1. 让我们再次运行我们的 webpack 脚本,如下所示:
npm run webpack

这将抛出另一个错误,如下所示:

ERROR in ./src/CustomArticle.vue
Module Error (from ./node_modules/vue-loader/lib/index.js):
[vue-loader] vue-template-compiler must be installed as a peer dependency, or a compatible compiler implementation must be passed via options
  1. 控制台中记录了更多错误,但我们需要通过添加另一个 NPM 包来解决这个。
npm install vue-template-compiler --save-dev --verbose

package.json中的devDependencies条目刚刚又更新了,如下所示:

  "devDependencies": {
    "html-webpack-plugin": "³.2.0",
    "vue": "².6.7",
    "vue-loader": "¹⁵.6.4",
    "vue-template-compiler": "².6.7",
    "webpack": "⁴.29.5",
    "webpack-cli": "³.2.3"
  }

所以,现在我们可以再次运行 webpack,如下所示:

npm run webpack

在 webpack 运行后,如果此时打开output.js,你会看到它里面有完整的 Vue 库,以及我们的CustomArticle在最后。所有这些都没有任何错误编译。

修复我们的 index.html 文件的问题

我们仍然有dist文件夹中的index.html文件的问题。这很容易解决!我们只需在src文件夹中添加我们自己的index.html文件,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Compiled HTML file</title>
</head>
<body>
    <div id="entryPoint"></div>
</body>
</html>

请注意,我们现在已经删除了自己的script标签,因为 webpack 将添加它们。另外,请确保删除dist文件夹中的index.html文件。现在,再次运行npm run webpack命令,你将在dist/index.html中得到以下输出:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack App</title>
  </head>
  <body>
  <script type="text/javascript" src="output.js"></script></body>
</html>

为什么这不起作用?

它不起作用,因为我们需要更新要输出的 JS 文件以及 HTML 文件。目前,我们只更新 JS 文件,但我们仍然需要为我们的index.html文件做同样的操作。幸运的是,我们已经有html-webpack-plugin来帮忙。

通过 html-webpack-plugin 使用 webpack 传递 HTML 文件

我们将首先更新webpack.config.js文件中的html-webpack-plugin如下:

plugins: [
    new HtmlWebpackPlugin({
        template: './src/index.html',
    }),
        new VueLoaderPlugin(), 
]

在插件部分所做的是,我们向HtmlWebpackPlugin()调用传递了一个options对象。在这个options对象内部,我们指定了我们的模板:./src/index.html

在我们再次运行 webpack 脚本之前,我们需要确保添加meta标签,并将charset设置为utf-8。否则,当我们在浏览器中打开dist/index.html时,我们将在控制台中收到错误。

现在让我们再次运行npm run webpack。这次,一切都正常!我们在屏幕上得到了我们看起来很简单的句子:

我们自己的自定义文章组件!

恭喜!虽然它看起来很简单,但您已成功将一个 Vue 应用程序添加到了运行在 webpack 上的 NPM 项目中。

接下来,我们将学习 HMR 以及它如何在 Vue 开发中帮助我们。

了解 Vue 中的热模块替换

HMR 在过去几年已经成为了一个热门词汇。这有什么了不起的?在本节中,我们将讨论 HMR 的工作原理。

为了做到这一点,我们将构建另一个默认的简单应用程序,就像我们在第一章中所做的那样,介绍 Vue CLI 3

vue create -d second-default-app

过一会儿,一旦完成,我们将按以下方式进入我们应用程序的目录:

cd second-default-app

让我们按以下方式在 VS Code 中打开项目文件夹:

code .

现在,我们可以看到整个second-default-project的内容。

现在,我们可以按以下方式提供应用程序:

npm run serve

当然,我们的应用程序现在正在浏览器中提供。

要查看您的应用程序,请在浏览器中访问localhost:8080

让我们实时查看 HMR 更新。

观察 HMR 更新

在浏览器窗口处于活动状态时,让我们按下F12键打开开发者工具。还要确保我们的元素面板是开发工具内的活动选项卡,这样我们就可以看到文档对象模型DOM)结构,就像在浏览器中放大的截图中一样:

图 2.2:打开开发工具中元素面板的 second-default-app 的欢迎屏幕

现在,让我们看看 HMR 的实际效果。理想情况下,要看到这一点,您需要使用两个监视器。因此,您可以将 VS Code 窗口移动到左侧监视器,将为应用程序提供的浏览器移动到右侧监视器。或者,您可以使用单个监视器并将两个应用程序并排查看(每个应用程序占据屏幕宽度的一半)。这个练习的重点是能够同时看到您的 VS Code 窗口、Vue 应用程序浏览器窗口和浏览器开发工具中的 Elements 面板。

接下来,在 VS Code 中打开项目的src文件夹中的App.vue文件。查看第 4 行,目前的内容如下:

<HelloWorld msg="Welcome to Your Vue.js App"/>

我们很快就会将该行更改为其他内容。在更改该行之前,请注意这些更改如何在为您提供应用程序的浏览器中反映。浏览器会刷新吗?

现在,您专注于跟踪浏览器中的更改,让我们按照以下方式更新App.vue中的第 4 行:

<HelloWorld msg="HMR is cool"/>

在保存App.vue中的更改时,请注意浏览器。最好的方法是让 VS Code 处于焦点状态,但要观察浏览器窗口,特别是 Elements 面板。将 VS Code 置于焦点状态,您可以使用快捷键Ctrl + S保存更改。

如果您仔细观察,并且正在使用 Chrome 浏览器,您会注意到 Elements 面板内出现了一道紫色的闪光。这是 Chrome 浏览器通知我们 Vue 应用程序的 DOM 发生了变化。如果您仔细观察,您会注意到head元素上有一道闪光,以及h1元素和其子文本节点HMR is cool上也有一道闪光。

您可能会注意到浏览器没有刷新。无论是 webpack、我们的应用代码还是我们自己都没有强制浏览器刷新。这里的结论是什么?Webpack 实际上并没有使用 HMR 强制刷新页面!相反,它只是注入了 HMR。

虽然h1元素的更改是显而易见的(因为它是我们更改App.vue文件中文本的直接可见结果),但在head元素中发生的更新既更加隐晦又更有帮助。为了看到发生了什么,让我们点击 Elements 面板中head标签左侧的小黑三角形展开 head 标签,如下面的截图所示:

图 2.3:在开发工具中的 Elements 面板中展开 head 标签

接下来,我们需要滚动到最后的</head>标签。在它的上方,会有一个类似于这样的script标签:

<script charset="utf-8" src="/app.c7e7b2f6599f49948328.hot-update.js"></script>

当我们对App.vue进行另一个更改时,让我们密切关注元素面板中 DOM 树的这一部分。让我们将第 4 行的msg属性更新为这样:

<HelloWorld msg="HMR is cool indeed"/>

如果你观察了script标签,你会注意到它的变化如下:

<script charset="utf-8" src="/app.417e697f270d544a21b3.hot-update.js"></script>

你有没有注意到 Vue 在闭合的</head>标签上面注入了另一个脚本?那个注入的脚本就是 HMR 在那里发挥作用。

让我们检查附加的脚本文件的第一行,如下所示:

webpackHotUpdate("app",{

整个过程是如何工作的呢?Webpack 简单地运行我们的更改,捆绑了我们应用程序的更新,并且,由于它已经在运行,使用 Vue 加载器注入了新的代码。

所以,正如我们刚才看到的,HMR 只是 webpack 的一个功能,帮助我们更顺畅地进行操作,而不需要担心刷新我们的应用程序。

摘要

在本章中,我们讨论了 JS 语言及其生态系统的演变,以及这种演变如何导致模块捆绑器的出现。我们还看了 webpack,这是 Vue CLI 3 的首选模块捆绑器。

我们看了如何插入一个非常基本的 Vue 应用程序,运行在单文件 Vue 模板上。除了这个小项目,我们还看了一些重要的 webpack 概念。我们通过观察 Vue 项目上的 HMR 来结束了本章。

现在我们知道了 webpack 的基本工作原理,在接下来的章节中,我们将讨论一些其他相关技术,并且在 webpack 和 Vue CLI 3 的知识基础上进行深入。我们将密切关注的下一个主题是 Babel。

第三章:Vue CLI 3 中的 Babel

在本章中,我们将使用 Babel 将JavaScriptJS)的新功能带到浏览器中,使其在浏览器能够理解之前将其转换为旧版本的 JS。我们将讨论以下内容:

  • 理解 Babel

  • 使用 ES5 和 ES6 运行 webpack

  • 更新我们的 webpack 配置以适配 Babel

  • Vue,Babel 和 JSX

  • 手动添加 Babel 插件

让我们首先看看 Babel 解决了什么问题。

理解 Babel

正如我们在之前的章节中已经看到的,一旦使用 Vue CLI 构建了默认的 Vue 应用程序,您可以使用npm run serve来提供它。

您的应用程序通常会在localhost:8080上提供。查看默认内容的服务页面时,您会注意到在已安装的 CLI 插件标题下列出了两个插件:babeleslint

为什么这两个插件会预先安装在默认应用程序中呢?显然,Vue 框架团队正在努力遵循最佳实践,并与构建 Web 应用程序的现代方法保持最新。使用 Babel 就是其中之一。

如果您访问 Babel 网站,您会看到以下关于它的定义:

“Babel 是一个主要用于将 ECMAScript 2015+代码转换为当前和旧版浏览器或环境中的 JS 的向后兼容版本的工具链。”

那么,我们如何使用 Vue CLI Babel 插件?以及获取有关它的更多信息的最简单方法是什么?

由于我们已经使用 Vue CLI 创建了默认的 Vue 应用程序,并且已经了解了 Vue CLI 的 UI,我们可以通过打开 Git Bash 并启动 Vue CLI UI 轻松地访问官方文档:

vue ui

正如我们在第一章中所看到的,介绍 Vue CLI 3,这个命令将使 webpack 在浏览器中为我们最新的项目仪表板提供服务。在那里,我们可以点击插件图标,如下截图所示:

一旦您点击了已安装的插件链接,您将看到以下屏幕:

此应用程序列出了三个默认安装的插件:@vue/cli-service@vue/cli-plugin-babel@vue/cli-plugin-eslint。为了更容易理解,其他插件已被灰掉,并且在截图中添加了编号框:

  1. 更多信息链接到cli-plugin-babel的 GitHub 存储库

  2. 更新@vue/cli-plugin-babel

  3. 带有主页图标的按钮是指向 Vue UI 项目管理器的链接,列出了所有可用的项目。

  4. UI 的这一部分显示了您的操作系统中当前 Vue 项目的位置

  5. 单击此处可让您切换 Vue UI 的日志开关

  6. 正如我们之前所看到的,这使您可以在 Vue UI 的两种颜色变化之间切换

  7. 报告错误图标将带您到 Vue-CLI 错误报告网页。

  8. 如果您有兴趣翻译 UI,此按钮链接到 UI 本地化页面

  9. 此图标仅刷新插件的 API

如果您需要使用流行的vuexvue-router插件,您可以简单地点击插件页面顶部的相应按钮来安装它们。

在“添加 vuex”和“添加 vue-router”按钮右侧的搜索输入框可让您过滤已安装的插件,“添加插件”按钮将带您转到localhost:8000/plugins/add屏幕,您可以从多个插件中进行选择,例如@vue/cli-plugin-unit-jest@vue/cli-plugin-typescript@vue/cli-plugin-pwa等。这里有大量的插件可供选择,我们将在后面的章节中更详细地了解它。

在下一节中,我们将讨论cli-plugin-babel的所有功能。

@vue/cli-plugin-babel 的构建模块

@vue/cli-plugin-babel默认提供了几个部分。这些是 Babel 7、babel-loader 和@vue/cli-plugin-babel

@vue/cli-plugin-babel 中的 Babel 7

这就是 Babel 解决的问题。

假设您正在开发您的 Web 应用的前端,并且正在使用 JS 语言的更现代的 ES6+语法。一旦您的应用程序完成,并发布到互联网上,您的一些用户在 Internet Explorer 上运行您的 Web 应用程序。与您的 Web 应用程序的其他用户相反,他们可以顺利运行您的应用程序,Internet Explorer 用户将收到语法错误。

Babel 就是对这样的问题的答案。它平衡了竞争环境:它允许开发人员将他们的 JS 浏览器兼容性问题外包给 Babel。他们不必再担心和迎合旧版浏览器,他们可以简单地使用语言的最新功能来编写他们的 JS 代码,甚至在任何浏览器完全支持之前。然后,Babel 负责将此代码转换为旧的 JS 方言,这是旧版浏览器可以理解的。

@vue/cli-plugin-babel运行在 Babel 7 上,Babel 7 于 2018 年 8 月 27 日发布。Babel 6 和 Babel 7 之间相差三年,这一迭代带来了一系列改进。Vue CLI 支持如此近期的更新是其团队致力于尽可能跟上时代的又一个证明。

@vue/cli-plugin-babel中 babel-loader 的作用

正如我们在前一章中看到的,Vue CLI 运行在 webpack 4 上。

为了能够使用 Babel 7,@vue/cli-plugin-babel使用 babel-loader,可以在这里找到:github.com/babel/babel-loader

如前一章所述,使用 webpack 加载器,我们可以预处理和捆绑一堆不同的资源,不仅仅是常规 JS,而是几乎任何其他静态资源。

具体来说,babel-loader接收 ES6+ JS,并将其转换为 ES5 JS。这个过程通常被称为转译。因此,@vue/cli-plugin-babel中 babel-loader 的作用是将我们的 ES6+代码转译为 ES5。

@vue/babel-preset-app的作用

@vue/cli-plugin-babel还有更多功能。它包括@vue/babel-preset-app,其唯一目的是在通过 Vue CLI 生成的项目中使用。在不深入讨论@vue/babel-preset-app的工作原理的情况下,我们可以列出其主要功能:

  • 它使用browserslist来查看您的浏览器目标

  • 它自动应用所需的转换和填充(借助@babel/preset-env实现)

  • 它增加了对 Vue JSX 的支持

  • 它阻止在构建过程中将所有文件中的辅助程序内联

除了之前列出的功能之外,@vue/cli-plugin-babel 还有其他功能,我们将在下一节中讨论它们。

@vue/cli-plugin-babel的其他功能

除了前一节中列出的默认设置,@vue/cli-plugin-babel也是可扩展的。我们可以使用babel.config.js添加其他 Babel 预设和插件。

它使用了一些 webpack 加载器来执行另外两个主要任务:缓存(借助 cache-loader 的帮助)和利用多核处理器(借助 thread-loader 的帮助)。这被称为并行化

在下一节中,类似于我们在第二章中所做的,Vue CLI 3 中的 Webpack,我们将介绍在 Vue 中设置 Babel 而不使用 CLI。之后,我们将看看 CLI 如何使事情变得更容易,以及如何进一步扩展。

在 Vue 2 中使用 Babel 和 webpack 而不使用 Vue CLI

让我们将我们的新项目命名为npm-vue-babel-webpack。我们将打开 Git Bash,添加此项目的文件夹,并cd进入其中:

mkdir npm-vue-babel-webpack && cd $_

我们将初始化 NPM 并接受所有默认设置:

npm init -y

在第二章中,Vue CLI 3 中的 Webpack,我们逐个安装了 NPM 包,解释了每个包的作用,并在此过程中修复了任何错误。这使我们对 webpack 的构建模块和 Vue 与 webpack 的配合方式有了深入的了解。为了避免不必要的重复,这次我们将一次性安装所有内容。

安装必要的 NPM 包

安装必要的 NPM 包:

npm install vue webpack webpack-cli html-webpack-plugin vue-loader vue-template-compiler --save-dev --verbose

现在将srcdist文件夹添加到我们的项目中,并在 VS Code 中打开我们的项目:

mkdir dist src && code .

随时在 VS Code 中检查package.json的内容,以确认所有 NPM 包确实已安装。

让我们在src文件夹内创建三个新文件,具体为main.jsApp.vueindex.html,几乎与我们在第二章中所做的一样,Vue CLI 3 中的 Webpack

以下是要添加到index.html中的代码:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="utf-8">
    <title>Compiled HTML file</title>
</head>
<body>
    <div id="entryPoint"></div>
</body>
</html>

以下是main.js的内容:

import Vue from 'vue';
import App from './App.vue';

new Vue({
    el: '#entryPoint',
    render: h => h(App),
})

最后,这是App.vue的内容:

<template>
  <div id="entryPoint">
      <article>
        Our own custom article component!
      </article>
      <AnotherComponent />
  </div>
</template>

<script>
import AnotherComponent from './components/AnotherComponent.vue';

export default {
    name: 'entryPoint',
    components: {
        AnotherComponent
    }
}
</script>

请注意,在上述script标签内部,我们正在从components文件夹中导入AnotherComponent

因此,让我们在项目的src文件夹内添加一个components文件夹。在components文件夹内,我们将添加一个新文件并将其命名为AnotherComponent.vue

接下来,将此代码添加到AnotherComponent.vue中:

<template>
  <p>
    This is another component.
    <button v-on:click="alertTime">What's the time?</button>
  </p>
</template>

<script>
export default {
  name: "AnotherComponent",
  data() {
    return {
    }
  },
  methods: {
    alertTime: function() {
      alert(new Date());
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

在上述代码中,我们终于看到了一个示例,其中我们的组件具有一些基本的 JS 驱动的 Vue 功能。我们正在使用 Vue 的内置datamethods选项。在methods选项内,我们定义了alertTime函数,每当它被调用时,都会在警报框中显示当前时间。

讨论所有这些组成部分如何运作的细节超出了本书的范围。本章的重点是理解 Babel。如果您需要更多关于 Vue 的基本概念的信息,比如前几段提到的内容,请参考 Packt 图书馆中的许多有用资源之一。本书的一个很好的伴侣将是对 Vue 2 框架的快速介绍:Vue.js 快速入门指南,作者是Ajdin Imsirovicprod.packtpub.com/in/application-development/vuejs-quick-start-guide)。

我们现在需要关注的重点是在我们的methods选项中使用 ES6+功能。目前,methods选项的代码是用 ES5 JS 编写的,因此很容易在此代码上运行 webpack,我们很快就会看到。

使用 ES5 代码运行 webpack

要运行 webpack,请执行以下操作:

  1. 在项目的根目录中添加另一个文件webpack.config.js,以便我们可以设置我们的 webpack 配置如下:
let HtmlWebpackPlugin = require('html-webpack-plugin');
let VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    entry: './src/main.js',
    output: {
        filename: 'main.js',
    },
    module: {
        rules: [
            { test: /\.vue$/, use: 'vue-loader' }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
        }),
        new VueLoaderPlugin(), 
    ]
};

请注意,入口和输出文件都是main.js,所以我们不必指定它们,但是在前面的代码中我们还是这样做了,以使事情更明显。

  1. 接下来,在package.json中,更新scripts键:
"scripts": {
    "webpack": "webpack"
 },
  1. 现在从 Git Bash 运行我们的项目,使用以下命令:
npm run webpack
  1. 现在,在 VS Code 中,导航到我们项目中的dist文件夹。

  2. 右键单击index.html,然后单击“在默认浏览器中打开”命令。

我们的浏览器现在将显示以下输出(放大以便查看):

如果用户单击“现在几点了?”按钮,将在网页上出现一个警报框,显示当前时间。现在让我们将我们的methods选项更新为 ES6 语法,然后看看会发生什么。

添加 webpack-dev-server

在我们开始将代码更新为 ES6 语法之前,还有一件事可以让事情变得更快捷和更方便:

  1. 添加webpack-dev-server。借助这个 NPM 包,我们的代码将不断地被提供和监视变化。让我们使用以下命令安装它:
npm install webpack-dev-server --save-dev --verbose
  1. 为了让 webpack 开发服务器运行并提供我们的代码,我们还需要将package.json条目的scripts更新为以下内容:
"scripts": {
  "webpack": "webpack",
  "webpack-dev": "webpack-dev-server --mode development"
},

现在我们可以尝试向我们的组件添加各种功能,并在我们在 VS Code 中保存代码时,观察它们在浏览器中进行热重载。

  1. 现在让我们立即通过运行以下命令来测试它:
npm run webpack-dev

您可以在http://localhost:8080/上测试提供的网页,并且您会注意到它仍然像以前一样工作。

接下来,我们将在methods选项中添加一些 ES6 语法。

将方法选项更新为 ES6 语法

让我们更新AnotherComponent.vue文件中的methods选项。以下是更新后的代码:

methods: {
    alertTime: () => {
      alert(new Date());
      alert('something else');
    }
}

一旦您在 VS Code 中保存了更改,您可以单击“现在几点了?”按钮,然后会出现预期的警报,然后是另一个读取其他内容的警报。这样,我们可以确保我们正在查看更新的应用程序。

现在让我们在dist文件夹中的编译后的main.js文件中找到我们的 ES6 代码。

如果我们在开发工具中检查/dist/index.html文件,我们可以看到对main.js的引用,这是 webpack 编译的 JS 代码。如果右键单击main.js并在上下文右键菜单中点击“在新标签页中打开”命令,您将在新标签页中看到完整的代码。要找到我们的 ES6 代码,让我们按下Ctrl + F快捷键,以便输入我们的搜索词:alertTime

在文件的底部,我们看到了我们的 ES6 箭头函数:

alertTime: () => {\r\n      alert('something else');

在接下来的部分,我们将使用 babel-loader 更新我们的 webpack 配置,并看看 webpack 将如何将前面的代码转译为 ES5。

将 babel-loader 添加到我们的 webpack 配置中

在开始之前,我们需要停止 webpack-dev-server,使用 Git Bash 中的Ctrl + C组合键。

接下来,为了能够在我们的项目中转译 ES6+语法,我们需要使用 Babel 更新我们的 webpack 配置。让我们首先使用 NPM 安装 babel-loader 包:

npm install babel-loader --save-dev --verbose

接下来,让我们再次在项目上运行 webpack:

npm run webpack

不幸的是,这仍然不起作用。如果我们检查我们转译后的main.js,我们仍然会看到alertTime键和它的 ES6 匿名函数。这意味着我们仍然需要另一个包:babel core

npm install @babel/core --save-dev --verbose

如果我们此时运行 webpack,我们会发现我们的问题仍然没有解决。

这意味着我们仍然需要添加babel-preset-env

npm install @babel/preset-env --save-dev --verbose

此时,验证一下我们的package.json中的devDependencies是否都有预期的更新是没有坏处的:

"devDependencies": {
  "@babel/core": "⁷.3.4",
  "@babel/preset-env": "⁷.3.4",
  "babel-loader": "⁸.0.5",
  "html-webpack-plugin": "³.2.0",
  "vue": "².6.9",
  "vue-loader": "¹⁵.7.0",
  "vue-template-compiler": "².6.9",
  "webpack": "⁴.29.6",
  "webpack-cli": "³.2.3",
  "webpack-dev-server": "³.2.1"
}

最后,在我们重新运行 webpack 之前,我们需要设置一个babel.config.js文件,这是 Babel 自己的配置文件(类似于 webpack 的webpack.config.js)。

让我们在项目的根目录中创建一个新文件babel.config.js,并添加以下代码:

module.exports = {
  presets: ['@babel/preset-env']
}

现在我们需要做的就是更新我们的 webpack 配置,使其能够与 Babel 一起工作。

更新我们的 webpack 配置以使用 babel

为了使我们的 webpack 能够使用 babel,我们需要告诉它何时使用 babel-loader。我们通过在webpack.config.jsmodule选项内添加一个测试规则来实现,如下所示:

module: {
    rules: [
        { test: /\.js$/, use: 'babel-loader' }, 
        { test: /\.vue$/, use: 'vue-loader' }
    ]
},

现在我们已经设置好了一切,我们可以再次在 Git Bash 中运行npm run webpack-dev命令。

这里有一个快速的方法来查看 webpack 是否与之前不同地捆绑了我们的 JS 文件:只需查看 Git Bash 中的 webpack 日志信息。在我们之前尝试将 Babel 与 webpack 配合工作时,捆绑大小恰好是 70.2 KB。然而,在webpack NPM 脚本的最后一次运行之后,main.js的捆绑大小为 70.6 KB。我们可以再次在开发工具中检查./dist/main.js文件。或者,你可以在 VS Code 中直接搜索./dist/main.js中的alertTime字符串。

无论我们如何定位它,我们捆绑的main.js文件的methods条目看起来是这样的:

methods:{alertTime:function(){alert(new Date),alert("something else")}}}...

仅仅瞥一眼前面的代码并看到function关键字,就应该明显地意识到这段代码是 ES5 的,这意味着 Babel 已经成功地被 webpack 运行,我们在src文件夹中的输入文件中的 ES6 alertTime Vue 方法已经成功地被转译到了dist文件夹中的输出文件中。

为了验证我们的设置是否有效,我们可以再次运行webpack-dev-server,并且在它运行时,对AnotherComponent.vue中的methods选项进行另一个小改动:

methods: {
    alertTime: () => {
      alert(new Date());
      alert('whatever');
    }
}

如果你查看在localhost:8080上提供的项目,你会看到它按预期工作,如果你从开发工具中打开main.js,你也会看到转译后的语法。

在下一节中,我们将简要提到一个常见的困惑来源以及在 Vue 中如何处理它。这与箭头函数语法和this关键字有关。

箭头函数中的 this 关键字在 Vue 中的问题

不幸的是,当 Babel 将箭头函数中的this关键字转译为_this时,这意味着我们的任何方法都将被破坏,我们的应用程序将无法工作。这背后的原因是箭头函数的作用域与 ES5 函数不同。

在下一节中,我们将看一下在 Vue 实例的方法选项中定义函数的推荐方法。

关键字问题的推荐解决方案

在 Vue 组件中解决this关键字的推荐解决方案是不使用箭头函数语法,因为由于作用域问题,它不会产生预期的结果。具体来说,箭头函数的作用域是父上下文。

让我们看一个简单的应用作为问题的例子。

添加一个计数器应用

在开始之前,请确保你回到了VUE-CLI-3-QSG/Chapter03文件夹,这是本章中所有项目的根文件夹。

在我们开始构建应用程序之前,我们需要提醒自己在使用vue create时有一些选项,因此让我们运行这个:

vue create --help

在选项列表中,我们可以看到-d代表--default标志,跳过提示并使用默认预设,而-b选项是--bare标志的简写,用于在不带初学者说明的情况下搭建我们的项目。

有趣的是,我们可以组合这些单独的标志,我们现在就来做。让我们通过运行以下命令来开始我们的应用程序:

vue create add-one-counter -db

正如我们所看到的,我们可以在vue create命令后附加的标志的字母别名之间进行链接,这是一个很好的小型生产力提升。

在构建的应用程序中,我们将更改src文件夹中的main.js的内容。这个文件将与之前的示例应用程序(上一节中的npm-vue-b-w-es6-syntax应用程序)完全相同,因此您可以将该文件从之前的 Vue 应用程序中复制并粘贴到我们的新示例应用程序add-one-counter中。

如果您在 VS Code 中打开我们的新的add-one-counter应用程序,您还会注意到另一个文件夹:public文件夹,其中包含index.html。我们将保留此文件不变。

回到src文件夹,我们需要更改App.vue的内容如下:

<template>
  <div id="app">
      <article>
        Our own custom article component!
      </article>
      <AnotherComponent />
  </div>
</template>

<script>
import AnotherComponent from './components/AnotherComponent.vue';

export default {
    name: 'app',
    components: {
        AnotherComponent
    }
}
</script>

最后,我们需要在项目的根目录下添加一个components文件夹,并在其中添加AnotherComponent.vue文件。以下是AnotherComponent.vue的内容:

<template>
  <p>
    This is another component.
    <button v-on:click="incrementUp">Add One</button>
    <br>
    <span>Current value of the counter: {{ counter }}</span>
  </p>
</template>

<script>
export default {
  name: "AnotherComponent",
  data() {
    return {
      counter: 0
    }
  },
  methods: {
    incrementUp: function() {
      this.counter++;
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

methods选项中,我们可以看到incrementUp函数使用 ES6 语法进行定义。

如果您尝试运行此应用程序,它将无法工作。这是因为箭头函数的作用域和 Babel 设置使得在arrow函数中正确设置 Vue 应用程序的methods变得困难。

唯一的改进,也是在方法选项中编写函数的通常方式,是避免使用箭头函数语法和function关键字的使用,如下所示:

methods: {
    incrementUp() {
        this.counter++;
    }
}

incrementUp函数被称为简写函数。您可以在以下网址阅读更多信息:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Method_definitions

让我们通过 UI 来测试驱动应用程序:

vue ui

一旦 Vue UI 在浏览器中提供服务,让我们将浏览器的地址栏指向http://localhost:8000/project/select。接下来,点击add-one-counter文件夹,然后点击导入此文件夹按钮。

接下来,点击主菜单上的 Tasks 按钮。最后,点击 Serve 图标。点击 Output 按钮查看应用程序的构建和服务情况。

最后,在http://localhost:8080/打开网站。你会看到一个正在提供服务的工作中的应用程序:

前面的例子向我们展示了如何在 Vue 实例中命名和组织方法的最佳实践。此外,我们还学会了如何使用 Vue UI 来自动化 webpack 的构建和服务应用程序,只需点击几下,比本章大部分内容中我们所做的要好得多!这让我们得出一个结论:很多的管道和功能都被抽象化了,因此,使用 Vue UI 和 Babel 设置变得更加容易和方便。

摘要

在本章中,我们简要概述了 Babel 是什么,它的作用以及使其与 Vue 一起工作所需的内容。所有这些都是通过vue-cli-service来抽象化的,它在幕后由 webpack 提供支持。现在我们已经了解了所有这些不同部分是如何一起工作的,我们将开始只使用 Vue CLI 及其 UI,并在接下来的章节中学习如何更好地使用它。

我们将从理解在 Vue CLI 中使用 Jest 进行测试开始。我们还将学习测试驱动开发(TDD)以及如何使用 Vue CLI UI 运行测试。

第四章:在 Vue CLI 3 中进行测试

在上一章中,我们研究了 Babel 在现代 JavaScript 开发中的作用。我们还看到了在 Vue 中使用它的一些实际例子。在本章中,我们将介绍 JS 中的测试。我们将了解测试的一般情况,并使用 Jest 和 Cypress 进行实践。我们将讨论断言和测试驱动开发TDD)。然后,我们将继续了解 Jest 和 Cypress 如何与 Vue CLI 3 一起工作。我们将讨论测试工具和测试用例。具体来说,我们将看以下内容:

  • 了解 Vue 插件

  • 将 Jest 插件添加到我们的 Vue 应用程序

  • 在 Vue 应用程序中使用 Jest 编写单元测试

  • 从项目任务页面运行任务

  • 在 Vue CLI UI 中运行单元测试

  • 使用断言

  • 实施 TDD

  • 使用 Cypress

我们将从对 Vue 插件的简要概述开始本章。

了解 Vue 插件

使用 Vue CLI 从命令行创建新的 Vue 应用程序时,我们使用vue create命令。然后,我们需要选择一些步骤和提示,以便正确配置我们的应用程序。实际上,我们正在选择我们的应用程序将使用哪些 Vue 插件,而其他事情。

插件是向我们的 Vue 项目添加功能的一种方式。有些插件比其他插件更复杂;它们有时在安装过程中会出现自己的提示。我们的 Vue 应用程序的配置,即底层代码,将反映我们的选择。我们的应用程序的设置方式将基于我们对这些安装提示的回答。

项目的所有官方npm包都使用@符号进行范围限定,后面跟着项目名称。因此,由 Vue 维护者构建的官方 Vue 插件以@vue开头。

要了解有关范围限定npm包的更多信息,请访问:docs.npmjs.com/about-scopes.

要从命令行添加插件,我们使用vue add命令,但我们也可以使用 Vue UI,正如我们将在本章中看到的那样。Vue UI 也是搜索 Vue 插件的好方法,我们也将在本章中进行研究。

在全新的 Vue 应用程序上开始测试

在之前的章节中,我们已经看到了 Vue CLI 和 UI 中许多不同的选项。我们将通过使用最佳方法来开始一个新应用程序,即 Vue CLI UI,来开始本章。这将帮助我们了解 UI 的一些其他功能。在此过程中,我们还将慢慢向我们的项目引入测试。

使用 Vue CLI UI 添加新项目

现在让我们使用 Vue CLI UI 添加新项目:

  1. 首先,让我们打开 Git Bash 并导航到所有项目的根文件夹vue-cli-3-qsg

  2. 现在我们将运行 Vue CLI UI 命令如下:

vue ui

这将导致浏览器中提供新页面。默认地址为http://localhost:8000/dashboard

  1. 接下来,单击主页图标(或者在地址栏中键入此 URL:http://localhost:8000/project/select),这将带您到 Vue 项目管理器屏幕。

请注意,主页图标是 Vue CLI UI 页脚中最左边的图标:

图 4.1:Vue CLI UI 中的主页图标

  1. 无论您如何访问 Vue 项目管理器屏幕,它都会显示可用应用程序的列表,以及顶部的三个选项卡:项目创建导入。单击“创建”选项卡以创建新项目。

  2. 单击“创建”选项卡后,您需要返回到项目的根目录,然后单击“在此处创建新项目”按钮如下:

图 4.2:创建,返回所有项目的根目录,点击“在此处创建新项目”按钮

一旦单击“在此处创建新项目”按钮,您将看到“创建新项目”屏幕。我们只会输入我们新应用程序的文件夹名称。我们将其称为testing-debugging-vuecli3。我们不会更改任何其他内容:我们将接受默认的软件包管理器和其他默认选项如下:

图 4.3:添加将容纳我们新应用程序的文件夹的名称

我们已经在“详细信息”选项卡中完成了所有必要的更改。

  1. 点击“下一步”按钮,我们将进入预设屏幕。在那里,我们可以接受默认预设(babel,eslint)如下:

图 4.4:接受默认预设

  1. 接下来,我们将单击“创建项目”以搭建我们的项目。Vue CLI UI 完成项目搭建需要一些时间。完成后,我们将看到“欢迎来到您的新项目!”屏幕。

向我们的 Vue 应用程序添加 Jest 插件

现在让我们添加我们的 Jest 插件:

  1. 点击插件图标(以下截图中标有数字 1)。

  2. 一旦项目插件屏幕出现,点击“添加插件”按钮(以下截图中的 2):

图 4.5:向我们的安装添加新插件

  1. 这将带我们到“添加插件”屏幕,在那里我们有一个输入字段来搜索插件。我们需要找到一个单元测试插件,所以我们可以输入cli-plugin-unit如下:

图 4.6:查找 Vue 的单元测试插件

  1. 输入此搜索词将显示所有可用的单元测试插件。Jest 应该就在顶部。您可以在上一张截图中看到它,标记为 2。在插件名称下的描述中,您可以看到它是一个官方插件。与我们已经看到的@vue/cli-plugin-babel类似,您可以单击“更多信息”链接以查看有关所讨论插件的相应 GitHub 存储库(在上述截图中标记为 3)。这样做将带您到 vue-cli GitHub 页面。

您可以在以下 URL 的npm包页面上找到有关@vue/cli-plugin-unit-jest的更多信息:www.npmjs.com/package/@vue/cli-plugin-unit-jest.

  1. 要安装 Jest 插件,只需在插件列表中单击它。这将在 Jest 插件旁边的绿色圆圈中添加一个复选框(在下一张截图中标记为 1)。还将出现一个新的安装按钮(在下一张截图中的框 2):

图 4.7:添加 Jest 插件

  1. 单击“安装@vue/cli-plugin-unit-jest”按钮将导致页面上出现加载器,并显示以下消息:安装@vue/cli-plugin-unit-jest....

  2. 完成后,只需单击“完成安装”按钮,如下所示:

图 4.8:完成 Jest 插件的安装

  1. 单击“完成安装”按钮将在屏幕上显示以下消息:调用@vue/cli-plugin-unit-jest....

  2. 更新完成后,我们将看到另一个屏幕,显示文件的更改,并要求我们提交所做的更新:

图 4.9:Vue CLI UI 在安装 Jest 插件后显示更改

检查更新

在上述截图中,我们可以看到“更改的文件”选项卡是活动的。在“更改的文件”选项卡中,我们可以看到更改的文件数量(框 1)。

在使用 Vue CLI UI 构建项目时,我们被默认选项要求使用 Git 跟踪项目的更改,我们接受了这个默认设置;这就是为什么我们现在看到在上一个截图中标记为 2 的提交更改按钮。

我们还可以看到对两个现有文件package-lock.jsonpackage.json所做的所有更改和更新,以及在安装插件时添加的三个新文件的内容:jest.config.jstests/unit/.eslintrc.jstests/unit/example.spec.js

检查每个文件的内容将是有益的,以便更熟悉它们的设置以及对它们进行了哪些更改。我们需要注意的最重要的更改之一是在package.json文件中的scripts键中,如下所示:

"test:unit":  "vue-cli-service test:unit"

前一行显示我们的vue-cli-service刚刚得到了一个新命令,test:unit,专门用于使用 Jest 进行单元测试。

一旦我们点击提交更改按钮,我们将看到一个对话框,邀请我们输入提交消息。我们可以输入一个简单的消息,比如添加 Jest 插件

在我们添加了提交之后,我们将被带回到已安装插件的屏幕。现在我们可以看到@vue/cli-plugin-unit-jest也已添加:

图 4.10:Vue CLI UI 在安装 Jest 插件后显示的更改

在接下来的部分中,我们将添加我们的应用程序,以便我们可以开始使用 Jest 进行测试。

添加我们的 Vue 应用程序的代码

要添加我们的应用程序,我们需要执行以下操作:

  1. 在 Windows 资源管理器中导航到testing-debugging-vuecli3文件夹。

  2. 接下来,在文件夹内的空白处右键单击,然后单击 Git Bash here 命令。

  3. 一旦 Git Bash 打开,输入code .并按下Enter键。这将在 VS Code 中打开我们的testing-debugging-vuecli3项目。

我们目前的重点是 Jest。为了避免不必要的复杂性,我们将简单地复制并粘贴上一章中的整个add-one-counter应用程序。最简单的方法是将 Windows 资源管理器指向add-one-counter应用程序,并在文件夹内右键单击启动另一个 Git Bash 实例,如前所述。我们将再次在 Git Bash 中输入code .命令,另一个 VS Code 实例将打开,这次显示add-one-counter应用程序内的文件。现在只需要将所有文件和文件夹从add-one-counter复制并粘贴到testing-debugging-vuecli3中。

或者,您可以在 Git Bash 中使用 Linux 命令来复制相关文件。

无论您如何操作,更新后的项目结构现在将如下所示:

图 4.11:testing-debugging-vuecli3 的更新项目结构

现在,我们准备使用 Jest 开始我们的第一个单元测试。

使用 Jest 在 Vue 应用程序中编写我们的第一个单元测试

tests文件夹中,还有一个名为unit的文件夹。让我们向unit文件夹添加一个新文件。我们将这个新文件命名为AnotherComponent.spec.js

任何具有spec.js扩展名的文件都将被 Jest 识别。

为了描述一个测试,我们使用describe函数,因此让我们将其添加到AnotherComponent.spec.js中,如下所示:

describe()

describe函数接受两个参数。第一个参数是我们正在测试的 Vue 组件的名称,第二个参数是一个匿名函数,如下所示:

describe('AnotherComponent.vue', function() {} )

我们可以使用箭头函数作为第二个参数来重写前面的代码,如下所示:

describe('AnotherComponent.vue', () => {})

在匿名函数的主体中,我们调用另一个函数,test函数,如下所示:

describe('AnotherComponent.vue', () => {
    test()
})

test函数接受两个参数:第一个参数是我们的测试名称,第二个参数是另一个匿名箭头函数,如下所示:

describe('AnotherComponent.vue', () => {
    test('Jest is setup correctly and working', () => {})
})

我们正在指定一个名为setup working的测试,并且我们需要在第二个参数内给出一个断言,也就是在匿名函数的主体内,如下所示:

describe('AnotherComponent.vue', () => {
    test('Jest is setup correctly and working', () => {
        expect(true).toBeTrue();
    })
})

这个断言将始终为真,因此我们给出以下代码:expect(true).toBeTrue()

我们刚刚看到了 Jest 匹配器的一个示例。匹配器是在 Jest 中测试值的一种方式。检查某些东西是否为真的一种方式是使用toBeTrue匹配器。还有许多其他 Jest 匹配器。有关更多信息,请查看以下 URL 的官方 Jest 文档:jestjs.io/docs/en/using-matchers.

现在,让我们转到 Vue CLI UI,并运行我们的单元测试。

在 Vue CLI UI 中运行我们的第一个单元测试

要在 Vue CLI UI 中运行我们的单元测试,我们需要导航到localhost:8080/tests页面,可以直接从地址栏访问该 URL,也可以通过单击 Vue CLI UI 仪表板中最左侧列中的最低图标(Vue CLI UI 仪表板中的 Tests 图标)来导航到该页面。一旦我们这样做,我们将看到以下测试列表:

图 4.12:查看 Vue CLI UI 中可用的任务

接下来,让我们准备点击test:unit任务来运行。这样做将导致在项目任务页面的右侧出现一个面板,如下所示:

图 4.13:运行 test:unit 命令的运行任务面板

这个运行任务面板给了我们一个很好的概览。现在让我们通过单击运行任务按钮来运行我们的测试。

以下信息将显示在输出部分:

...
... 
PASS tests/unit/AnotherComponent.spec.js

Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.702s
Ran all test suites.

Total task duration: 3.93s

正如我们所看到的,我们的AnotherComponent.spec.js测试已经成功通过。在AnotherComponent.spec.js测试之前,有一个测试失败并记录输出的测试,那就是HelloWorld.vue组件的测试。我们在 Vue UI 构建应用程序后,已经将HelloWorld.vue文件从默认应用程序中移除了。

然而,./tests/unit文件夹中的example.spec.js文件是调用不存在的HelloWorld.vue文件的test文件。查看example.spec.js,我们可以看到它在第 2 行导入了HelloWorld.vue组件,如下所示:

import HelloWorld from '@/components/HelloWorld.vue'

为什么会这样呢?难道我们不是已经在describe函数中指定了AnotherComponent.vue吗?

事实证明,我们可以在我们的单元测试中的 describe 函数的第一个参数中指定任何名称。例如,我们可以将我们的AnotherComponent.spec.js文件更新为以下代码:

describe('whatever', () => {
    test('Jest is setup correctly and working', () => {
        expect(true).toBeTrue();
    })
})

如果我们再次运行我们的测试,它仍然会运行。

这意味着字符串AnotherComponent.vue是我们开发者作为第一个参数传递给我们的describe函数的,这样我们在项目中更容易工作。Jest 不在乎它的名字是什么。

然而,它在乎的是导入要测试的文件。正如我们在HelloWorld.vue导入中看到的,我们需要在我们的AnotherComponent.spec.js文件中添加一个类似的导入,这样现在它看起来如下:

import AnotherComponent from '@/components/AnotherComponent.vue';

describe('AnotherComponent.vue', () => {
    test('Jest is setup correctly and working', () => {
        expect(true).toBeTrue();
    })
})

有趣的是,我们导入了一个 Vue 文件,但我们的测试仍然通过,即使.vue扩展名不是 JS。这是如何实现的?

如果我们打开位于项目根目录的jest.config.js文件,我们可以很容易地看到发生了什么。查看这个文件的前 12 行,我们会看到以下代码:

module.exports = {
  moduleFileExtensions: [
    'js',
    'jsx',
    'json',
    'vue'
  ],
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
    '^.+\\.jsx?$': 'babel-jest'
  },

正如我们所看到的,vue扩展名在第 6 行上列出,.vue文件扩展名将使用vue-jest插件进行转换,如第 9 行所指定的。

在我们继续之前,让我们将我们的example.spec.js文件重命名为example.js,这样 Jest 就不会捕捉到它。我们仍然需要文件的内容,所以让我们不要删除它,而是只是重命名它。

从 test-utils 导入 mount 并编写另一个单元测试

我们将从@vue/test-utils中的mount导入开始,放在我们的AnotherComponent.spec.js文件的第一行,如下所示:

import { mount } from '@vue/test-utils';

在我们继续之前,我们需要看一下这个语法的作用。为什么在mount周围有花括号?

要回答这个问题,了解这是被接受的 JS 语法是很重要的。为了解释发生了什么,我们需要从package.json文件开始。

这个文件是由我们的 Vue CLI 在构建项目时创建的。如果我们查看package.json文件的内容,我们会看到@vue/test-utils被列为我们项目的devDependencies之一。

在前面的代码中,我们从@vue/test-utils JS 模块中导入了一个单一函数mount。通过这样做,我们将mount函数插入到我们的AnotherComponent.spec.js文件的作用域中。

简单来说,我们从@vue/test-utils导入mount功能,这样我们就可以在AnotherComponent.spec.js文件中使用它,并且只测试这个组件。

在我们的浏览器中运行 Vue CLI UI,让我们通过访问以下 URL 来查看我们项目的依赖列表:http://localhost:8000/dependencies

你应该会看到类似以下截图的屏幕:

图 4.14:Vue CLI UI 仪表板中列出的项目的 devDependencies

像往常一样,点击@vue/test-utils项目依赖项的“更多信息”链接将带我们到该项目对应的 GitHub 存储库:github.com/vuejs/vue-test-utils#readme.

挂载要测试的组件

我们首先导入mount方法和要测试的组件,如下所示:

import { mount } from '@vue/test-utils';
import AnotherComponent from '@/components/AnotherComponent.vue';

mount函数接收一个组件作为其参数。调用mount函数的结果是一个包装器,其中包含我们给定的组件的实例。这个包装器还带有帮助我们测试过程的附加函数。让我们首先将调用mount(AnotherComponent)的返回值分配给一个变量,如下所示:

import { mount } from '@vue/test-utils';
import AnotherComponent from '@/components/AnotherComponent.vue';

describe('AnotherComponent.vue'), () => {
  test('Adds one when a user clicks the button', () => {
  const wrapped = mount(AnotherComponent);
}

编写一个失败的断言

当我们的应用程序最初加载到浏览器中时,我们期望计数器的当前值为0。然而,由于我们希望我们的断言最初失败,让我们断言计数器的值将是1而不是0,如下所示:

import { mount } from '@vue/test-utils';
import AnotherComponent from '@/components/AnotherComponent.vue';

describe('AnotherComponent.vue'), () => {
  test('Adds one when a user clicks the button', () => {
  const wrapped = mount(AnotherComponent);
  expect(wrapped.text()).toContain('Current value of the counter: 1');
}  

在上述代码中,我们已经编写了一个失败的断言。我们声称我们期望我们的包装组件将包含以下文本:

Current value of the counter: 1

我们的计数器的初始值不会是1;实际上将是0,因此前面的断言应该失败。

因此,让我们保存并运行我们的单元测试,方法是转到项目任务屏幕,并按照本章前面描述的方式运行测试。

输出将显示在项目任务中的 Run task 的输出面板中,如下所示:

Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 1.947s
Ran all test suites.

Total task duration: 3.14s

接下来,我们将通过编写一个通过的断言来修复前面的测试。

编写一个通过的断言

要编写一个通过的断言,我们只需要将我们的1恢复为0,如下所示:

expect(wrapped.text()).toContain('Current value of the counter: 0');

接下来,让我们在 Vue UI 中再次运行我们的任务,然后我们将得到以下输出:

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.418s
Ran all test suites.

Total task duration: 3.55s

接下来,我们将在我们的测试中触发一个按钮点击。

在我们的测试中触发按钮点击

我们如何在单元测试中测试按钮点击?执行以下步骤:

  1. 我们需要找到要点击的按钮。这很容易,因为我们的应用程序中只有一个按钮。我们将使用find方法来做到这一点。

  2. 我们将使用trigger方法触发按钮点击。

  3. 我们需要检查计数器的值是否从0变为1。然而,由于我们首先需要编写一个失败的测试,我们将编写以下代码:

import { mount } from '@vue/test-utils';
import AnotherComponent from '@/components/AnotherComponent.vue';

describe('AnotherComponent.vue', () => {
  test('Adds one when a user clicks the button', () => {
    const wrapped = mount(AnotherComponent);
    expect(wrapped.text()).toContain('Current value of the counter: 0');
    const button = wrapped.find('button');
    button.trigger('click');
    expect(wrapped.text()).toContain('Current value of the counter: 0');
  })
})

如预期的那样,在 Vue CLI UI 中运行我们的测试的输出如下:

Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 2.383s
Ran all test suites.

Total task duration: 3.55s

通过编写两个测试并断言它们以使它们都通过,让事情变得更有趣,如下所示:

import { mount } from '@vue/test-utils';
import AnotherComponent from '@/components/AnotherComponent.vue';

describe('AnotherComponent.vue', () => {
    const wrapped = mount(AnotherComponent);
    const button = wrapped.find('button');
    test('Checks that the initial counter value is 0', () => {
        expect(wrapped.text()).toContain('Current value of the counter: 0');
    });
    test('Adds one when a user clicks the button', () => {
        button.trigger('click');
        expect(wrapped.text()).toContain('Current value of the counter: 1');
    })
})

让我们再次保存我们的测试,并在 Vue CLI UI 中再次运行它作为一个任务。

以下是输出:

AnotherComponent.vue
    √ Checks that the initial counter value is 0 (3ms)
    √ Adds one when a user clicks the button (4ms)

Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 2.307s
Ran all test suites.

Total task duration: 3.64s

我们已经成功地在一个测试套件中为 Vue 组件编写了两个单独的单元测试,并且我们的两个测试都通过了。

在 Vue CLI 3 中的测试驱动开发

TDD 是基于“红-绿-重构”周期的开发。与我们在前面的代码中看到的类似,我们首先编写我们的代码,使我们的测试失败。接下来,我们编写我们的代码,使我们的测试通过,最后我们重构我们的代码。

对于我们应用程序中的每个新功能,我们重复相同的过程。这本质上就是 TDD。

TDD 只是以一种简化的方式在任何语言或框架中编写任何应用程序。它通过允许我们将整个项目分割成可测试的、清晰分离的功能块来简化我们的工作。

红绿重构方法在项目任务页面的输出中也是清晰可见的。如果我们编写一个失败的测试,我们会看到单词“fail”的背景是红色的。如果我们编写一个通过的测试,我们会看到单词“pass”的背景是绿色的。

在本章的其余部分,我们将通过 Vue CLI 3 的帮助来了解与测试相关的一些其他概念。

在 Vue CLI 3 中改进我们的测试

我们可以利用 Jest 和其他测试平台在 Vue CLI 3 中进行更好的测试体验的几种方式。在接下来的章节中,我们将看到以下内容:

  • 在 Vue CLI 3 中观察我们的单元测试

  • 为我们的任务设置参数

  • 使用 Cypress 编写端到端测试

让我们从使用 --watch 标志开始。

在 Vue CLI 3 中观察我们的测试

test:unit 命令带有 --watch 标志。要看到它的效果,我们只需要回到 Vue UI 中的项目任务页面,并在选择 test:unit 任务后,点击参数按钮,如下所示:

图 4.15:test:unit 任务中的参数按钮

点击参数按钮将触发一个对话框,其中包含以下两个选项:

  • 监视文件以进行更改并重新运行与更改文件相关的测试

  • 在此测试运行期间重新记录每个失败的快照

点击第一个选项以打开观察模式。接下来的选项将立即出现在其下方:

  • 在每次运行后显示通知

这个选项只有在观察模式启用时才可用。让我们也启用每次运行后显示通知选项,并点击保存。

你可以在package.json的 scripts 中设置这些选项。第一个选项是--watch,显示通知选项是--notify标志。

要做到这一点,只需更新项目的package.json中的 scripts 键到以下代码:

"scripts": {
  "serve": "vue-cli-service serve",
  "build": "vue-cli-service build",
  "lint": "vue-cli-service lint",
  "test:unit": "vue-cli-service test:unit",
  "test:unit-watch": "vue-cli-service test:unit --watch --notify"
},

你会看到你的任务列表现在已经扩展到包括另一个测试任务:test:unit-watch

然而,即使你可以,最好不要这样做。这不是最佳实践,而且这样做有点违背了使用 Vue UI 的初衷。不过,了解到这样可以做的话,我们对 Vue CLI UI 底层发生了更好的理解。

现在,让我们通过向AnotherComponent.spec.js文件添加更改来查看观察模式是否正常工作。只需在某个地方添加一个空格并保存更新即可。

使用 Cypress 编写端到端测试

端到端测试是一种测试实践,我们在其中从头到尾测试应用程序的流程。通过端到端测试,我们模拟用户从某种入口点流经我们的应用程序到达某种结果的场景。

例如,Web 应用程序的端到端测试可能包括以下流程:

  • 用户在浏览器中打开 Web 应用程序的 URL

  • 用户点击登录链接并登录

  • 用户在 Web 应用程序中检查通知

  • 用户登出

介绍 Cypress

在本节中,我们将使用 Cypress 进行端到端测试。Cypress 在 Chrome 浏览器中运行良好。或者,如果你想使用基于 Selenium 的工具,你可以在这个网站上查看 Nightwatch.js:nightwatchjs.org/.

要了解更多关于 Cypress 的信息,请访问以下网址的官方网站:www.cypress.io/

如果你访问 Cypress 网站,你会看到它被描述为:

快速、简单、可靠的测试任何在浏览器中运行的东西。

让我们马上开始吧。

向我们的项目添加 Cypress 插件

现在让我们在运行 Vue CLI UI 的情况下向我们的项目添加一个 Cypress 插件:

  1. 在浏览器中打开以下地址:

http://localhost:8000/plugins/add

  1. 接下来,在搜索框中输入cypress,并找到@vue/cli-plugin-e2e-cypress插件。

  2. 按照我们之前使用 Jest 插件的方式,按照插件安装步骤进行操作。

  3. 一旦我们添加了 Cypress 插件,我们需要提交更改。与 Jest 一样,我们可以只用一个简单的消息提交,比如“添加 Cypress 插件”。

注意,安装 Cypress 会在我们的tests文件夹中添加一个名为e2e的新文件夹。在e2e文件夹中,我们可以找到以下子文件夹:pluginsspecssupport

让我们接着检查package.json文件的内容。

验证 Cypress 插件安装后对 package.json 的更新

让我们在 VS Code 中检查我们项目的package.json。我们会注意到scripts选项中有一个新的条目,如下所示:

"test:e2e": "vue-cli-service test:e2e",

此外,我们的devDependencies已经通过 Cypress 插件进行了更新,我们还可以通过访问 Vue UI 仪表板并检查已安装的插件来看到这一点。

最后,如果我们点击任务图标,我们会看到test:e2e任务已添加到我们项目的任务列表底部,与我们在package.json文件中看到的完全相同。

如果我们点击test:e2e任务,右侧窗格将相应更新,运行任务按钮已准备好点击。点击运行任务按钮将产生以下输出:

$ vue-cli-service test:e2e --mode development
 INFO Starting e2e tests...
 INFO Starting development server...

 DONE Compiled successfully in 1691ms18:06:27

  App running at:
  - Local: http://localhost:8082/
  - Network: http://192.168.1.70:8082/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

It looks like this is your first time using Cypress: 3.2.0

[18:06:28] Verifying Cypress can run C:\Users\W\AppData\Local\Cypress\Cache\3.2.0\Cypress [started]

[18:06:30] Verified Cypress! C:\Users\W\AppData\Local\Cypress\Cache\3.2.0\Cypress [title changed]

[18:06:30] Verified Cypress! C:\Users\WAppData\Local\Cypress\Cache\3.2.0\Cypress [completed]

Opening Cypress...

一个新的由 Electron 驱动的窗口将在我们的计算机上打开。使用 Cypress 很容易。正如“帮助您入门……”窗口所告诉我们的那样,您可以在examples文件夹中运行测试,或者将您自己的测试文件添加到cypress/integration中。

如果您看一下 Cypress 窗口右上角,您会看到“运行所有规范”按钮。默认情况下,它将在 Chrome 中运行(指定版本号)。如果您点击下拉菜单,选择 Chrome,您可以切换到 Electron。无论您选择哪个选项,您的测试都将在一个新窗口中运行,无论是一个新的 Chrome 窗口还是一个新的 Electron 窗口。

此时,我们的端到端 Cypress 测试将失败,因为 Cypress 试图在默认的 Vue 脚手架项目上运行测试,如下所示:

图 4.16:Cypress 中的一个失败测试

如果您希望从一开始就看到这些测试通过,您需要创建一个全新的项目,并在配置中设置 Cypresse2e测试。我们将在本书的后面看看这些不同的选项。现在,让我们更新我们的测试,使它们通过。

更新我们 Vue 应用中的 Cypress 测试

回到 VS Code,在./tests/e2e/specs/文件夹中打开test.js文件。您会看到一个带有两个参数的describe函数。

要更好地理解 Cypress 术语,请参考以下网址:

docs.cypress.io/guides/core-concepts/writing-and-organizing-tests.html#Support-file,以及

docs.cypress.io/guides/references/bundled-tools.html#Mocha.

在 Jest 中,我们看到test这个词作为单元测试函数的名称,而在 Cypress 中,我们看到使用it这个词。cy对象是实际的 Cypress 测试运行器。让我们看一下test.js文件的以下更新代码,并解释它是如何以及为什么工作的:

describe('My First Test', () => {
  it('Visits the app root url', () => {
    cy.visit('/')
    cy.contains('article', 'Our own custom article component!')
  })
})

这次我们的测试通过了。请注意,我们只需要在 VS Code 中保存更新后的测试文件,测试就会自动运行。您可以转到http://localhost:8000/tasks/,并单击test:e2e任务以获取有关正在运行的任务的更多信息,如下所示:

图 4.17:我们 Vue 应用程序主页的 Cypress 测试通过的屏幕截图

另外请注意,如果你在测试结果上悬停在“CONTAINS”部分,那么服务的 Vue 应用程序的适当部分将被突出显示,这是一个关于我们正在测试的 Vue 应用程序的确切部分的美妙视觉提示。

Summary

在本章中,我们通过 Vue CLI 3 的视角讨论了许多与测试相关的主题。TDD 是一种很棒的技术,应该被团队和个人广泛利用,而 Vue CLI 3、它的 UI 和 Jest 是优化这一过程的绝佳选择。与 Vue CLI 3 的其他方面一样,很多的管道工作都对我们隐藏起来,这使得编码体验非常棒。

在下一章中,我们将研究 Vue CLI 3 中的路由。

第五章:Vue CLI 3 和路由

在上一章中,我们看到了如何在 Vue 中使用一些测试套件,比如 Jest 和 Cypress。在本章中,我们将看看如何使用 vue-router,并将其与 Vue CLI 3 一起使用。我们将看一些实际任务,比如懒加载组件。我们将看看使用 Vue add 命令添加 vue-router 的原因以及如何减轻其影响的步骤。如果您想构建更大更复杂的应用程序,了解 Vue 中的路由是有益的。本章涵盖的主题如下:

  • 使用 vue-router 和 vuex 添加一个新的 Vue 项目

  • 通过 VS Code 的命令行配置预设选项

  • 理解 vue-router 路由

  • 使用命名路由

  • 添加动态路由

  • 从 Vue 实例的方法选项导航到一个路由

  • 使用嵌套(子)路由

  • 懒加载路由

我们将从添加一个新项目开始。

使用 vue-router 和 vuex 添加一个新的 Vue 项目

让我们从在文件系统中创建一个新文件夹开始。让我们把这个文件夹叫做vueclichapter5

  1. 从 Windows 资源管理器中打开vueclichapter5文件夹,在vueclichapter5文件夹内的空白处右键单击,然后单击“Git Bash here”命令。

  2. 一旦 Git Bash 打开,输入code .并按Enter键。这将打开一个全新的 VS Code 实例,除了欢迎标签之外,没有其他文件或选项卡。

  3. 接下来,我们将直接从 VS Code 的集成终端中添加一个新的 Vue 项目。要访问这个终端,点击 VS Code 窗口(使其获得焦点),然后按以下快捷键:Ctrl + `

我们之前已经提到了Ctrl反引号快捷键。作为提醒,`字符可以在键盘上按下Tab键上方的键时找到。

使用Ctrl + `键盘快捷键将在 VS Code 中打开终端。

  1. 接下来,我们将运行vue create命令,后面跟着一个点,如下所示:
vue create .

这样做将在现有文件夹中生成一个 Vue 项目,也就是说,它不会为我们的新 Vue 项目创建一个子文件夹,如下所示:

图 5.1:从 VS Code 的终端在当前目录中生成项目

  1. 按下Y键确认我们将在当前目录中生成我们的项目。

通过 VS Code 的命令行配置预设选项

接下来,我们将通过按一次向下箭头键,然后按Enter键来选择手动选择功能选项,如下面的屏幕截图所示:

图 5.2:从 VS Code 的终端在当前目录生成一个项目

添加 vue-router 和 vuex

接下来,我们将使用向下箭头键和空格键来选择 Router 和 Vuex 作为我们项目中的附加功能,如下截图所示:

图 5.3:向我们的项目添加 vue-router 和 vuex 插件

一个提示会询问我们是否要为路由使用历史模式。

我们现在不想使用它,所以我们只需输入n并按Enter

在本章的后面,我们将讨论历史模式的作用和工作原理。

添加 ESLint 和 Prettier

另一个提示询问我们关于我们的代码检查器或格式化程序的偏好。我们将使用 ESLint 和 Prettier,如下所示:

图 5.4:选择 ESLint 和 Prettier 作为我们的代码检查器/格式化程序配置

完成配置

最后,我们将接受默认的保存时 Lint 功能,并选择将 Babel、PostCSS、ESLint 等配置放在专门的配置文件中,如下所示:

图 5.5:选择将配置保存在专门的配置文件中

最后,Vue CLI 会询问我们是否要将此设置为将来项目的预设。目前我们会选择不保存。

为我们的新项目安装所有插件

最后,Vue CLI 会安装所有插件,如下所示:

图 5.6:Vue CLI 正在安装我们项目的插件

安装完成后,我们将拥有一个已安装 vue-router 和 vuex、ESLint 和 Prettier 设置好并准备使用的 Vue 项目。

通过 Vue CLI UI 为我们的项目提供服务

项目安装完成后,我们可以使用npm run serve命令来运行它。但是,我们将使用 Vue CLI UI 来运行它,所以让我们按照以下步骤使用vue ui

图 5.7:通过 vue UI 命令从 VS Code 命令行中为我们的项目提供服务

正如预期的那样,我们的 Vue CLI UI 将自动在浏览器窗口中打开,网址为http://localhost:8000/dashboard。此时,旧项目可能会加载在仪表板中,所以我们需要点击主页图标并导入我们的新vueclichapter5项目。

请注意,我们本来可以从一开始就使用 Vue CLI UI 安装新应用,但有趣的是,您可以在命令行和 UI 之间切换而不会出现问题。

项目加载完成后,我们可以点击插件链接以查看已安装的插件。请注意,缺少Add vue-routerAdd vuex按钮。它们不存在,因为我们已经安装了它们。

从 UI 中运行 serve 任务

最后,我们将点击任务图标以打开可用任务列表,然后点击 serve 任务以编译和提供我们的项目。就像以前一样,运行任务面板将出现在仪表板的右侧,如下所示:

图 5.8:运行 npm run serve 脚本的任务

在上面的截图中,我们可以看到 serve 任务屏幕的放大部分。点击运行任务按钮将开始构建应用程序,并且我们将在 Windows 开始栏上收到通知,我们的应用程序已成功构建。查看可用的选项卡,我们可以看到当前视图显示了我们 serve 任务的仪表板。点击当前活动的 serve 任务仪表板按钮左侧的输出按钮将显示日志信息,如下所示:

  App running at:
  - Local: http://localhost:8082/
  - Network: http://192.168.1.70:8082/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

当然,vue-cli-service将为我们的 Vue 应用提供服务的特定端口将取决于其他已经在使用的端口。现在,要在浏览器中打开我们正在运行的 Vue 应用,只需点击输出日志中列出的LocalNetworkURL 之一即可。

在 vue-router 中使用路由

在接下来的部分中,我们将研究 vue-router 中的路由工作原理,以及如何使用它们添加页面和路由。我们将从检查现有路由开始,然后添加额外的路由和它们对应的组件。

检查两个默认路由

这将打开一个带有 Vue 标志的熟悉的起始项目,稍作添加:顶部有一个链接指向关于页面,如下截图所示:

图 5.9:安装了 vue-router 的项目的默认导航

如果您点击关于链接,您将看到另一个页面,其中有一个h1标签,里面是以下文本:

This is an about page

请注意,关于页面的路由在页面名称前面有一个井号。在我们的示例应用程序中,它看起来像这样:http://localhost:8082/#/about.我们如何去掉井号?换句话说,我们如何将地址设置为http://localhost:8082/about

答案很简单,我们只需要设置我们的服务器始终返回index.html页面,然后我们将添加另一个设置,即 vue-router 的mode设置,如下所示:mode: 'history'

您需要在router.js中的export default new Router({行下面添加上述代码。这样做将去掉井号。

接下来,我们将检查预安装了 vue-router 和 vuex 的项目的内容。

检查项目文件

返回 VS Code 并查看项目结构。您会看到与以前不同的一些差异。以下是我们src文件夹的内容:

图 5.10:带有预安装的 vue-router 和 vuex 的 src 文件夹的内容

src文件夹中,我们可以看到一个以前没有见过的文件夹:views文件夹,其中包含两个视图文件:Home.vueAbout.vue。在我们项目的根目录中,我们还可以看到一些额外的文件:router.jsstore.js.browserslistrceslintrc.jspostcss.config.jsREADME.md

router.js文件是 vue-router 用来设置应用程序中路径的文件。routes数组是一组对象:一个对象对应一个路由。由于默认安装中有两个路由,所以routes数组中有两个对象。store.js文件是 vuex 用来跟踪我们应用程序的状态、mutations 和 actions 的文件;这些都被称为vuex storeREADME.md文件列出了与我们的应用程序一起使用的常见 npm 命令,我们项目根目录中的其他文件都是配置文件;在我们通过 Vue CLI 3 的旅程中的这一点上,这应该是可以预期的。

main.js 的内容

就像我们以前看到的那样,src文件夹中的main.js文件导入了所有以下依赖项:

  • 来自node_modules的 Vue 库

  • 根组件App.vue

  • 设置 vue-router 路由的路由器文件

  • 设置 vuex store 的 store 文件

App.vue 文件和 router-link 导航

通过检查根组件App.vue的内容,我们可以看到该文件与以前不同:没有script部分!

此外,App.vue内的模板标签包含所谓的导航组件。每个导航项都包含在router-link标签内。

为什么不只使用锚标签而不是router-link标签?因为锚标签会继续发送服务器请求。使用router-link标签可以避免这种行为。

如果我们检查dist文件夹中编译的 HTML 代码,我们将看到捆绑的 HTML 确实最终成为一个锚标签,如下所示在编译的生产代码中所见:

<div id="nav">
    <a href="#/" class="router-link-active">Home</a> |
    <a href="#/about" class="router-link-exact-active router-link-active">About</a>
</div>

回到view文件夹内的Home.vueAbout.vue文件,我们还可以看到router-view标签(在具有idnavdiv下方)。这实际上是渲染Home viewAbout view的地方。将要渲染的组件将由与to属性映射的内容确定。

渲染 Vue 实例并将其挂载到#app

最后,调用一个 Vue 的新实例,并传递一个选项对象作为参数。该对象接收以下键值对:router: routerstore: storerender: h => h(App)

用 ES5 代码编写,该代码看起来如下:

new Vue({
    router: router,
    store: store,
    render: function render(h) {
        return h(App);
    }
}).$mount("#app");

我们的main.js文件幸运地采用了更现代的语法,因此当所有这些东西放在一起时,它看起来如下:

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount("#app");

渲染方法将获取我们应用程序的所有不同部分,将它们组合在一起,并准备好挂载。最后,我们的 Vue 应用程序将被挂载到./public/index.html中具有id为 app 的div内。

您可能会注意到我们当前应用程序的目录中没有dist文件夹。正如我们在第二章中学到的,Vue CLI 3 中的 Webpackdist文件夹是 webpack 构建我们网站的产物。因此,让我们接下来在 Vue CLI 3 UI 中运行构建任务,以查看dist文件夹被创建和提供。

从 UI 中运行构建任务

要从 Vue CLI 3 UI 中运行构建任务,我们只需要转到http://localhost:8000/tasks/,然后点击构建任务,然后点击运行任务按钮。

我们运行的构建任务的输出选项卡将记录以下信息:

  File Size Gzipped

  dist\js\chunk-vendors.1030118d.js 116.48 KiB 40.51 KiB
  dist\js\app.51b1d496.js 5.97 KiB 2.23 KiB
  dist\js\about.d288b4f1.js 0.44 KiB 0.31 KiB
  dist\css\app.08e7a232.css 0.42 KiB 0.26 KiB

  Images and other types of assets omitted.

 DONE Build complete. The dist directory is ready to be deployed.
 INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html

./dist/js/文件夹中的这些不同的 JavaScript 文件是什么?它们是 webpack 将我们的 Vue 应用程序的单文件组件、路由和存储打包成部署准备的捆绑包的结果。这些捆绑包现在已添加到编译和缩小的index.html页面中,位于我们的dist文件夹内,因此这就是它们最终出现在我们的生产就绪网页上的方式。

最后,让我们看看我们更新后的应用程序。为此,我们将单击 serve 任务,并通过单击停止任务按钮来停止任务。

从 UI 中以生产模式提供应用程序

要以生产模式提供应用程序,我们需要单击 serve 任务选定的 Run 任务面板内的参数按钮。

一旦单击参数按钮,我们将看到以下对话框:

图 5.11:在 Vue CLI 3 UI 中 serve 任务的参数对话框中指定 env 模式

在指定 env 模式设置中,单击下拉菜单,然后选择生产模式。保存更改,然后您将再次看到 serve 任务仪表板。现在,单击运行任务按钮。最后,为了确保一切仍然正常工作,请将浏览器指向 Vue 应用程序正在提供的任何端口。在本例中,正确的地址是http://localhost:8082/。接下来,单击关于链接。

回到 VS Code,将About.vue页面的h1标签更改为以下内容:

<h1>This is an about page. HMR rocks!</h1>

保存文件并查看您的关于页面是否获得了 HMR 更新。

一些处理路由的基础知识

尽管本书是关于 Vue CLI 3 的,但我们将利用这个机会快速列出一些 vue-router 的特性。这绝不是一个详尽的列表:它只是对您需要了解的某些特性的快速概述:

  • 使用命名路由

  • 添加动态路由

  • 从 Vue 实例中的方法选项导航到路由

  • 使用嵌套(子)路由

  • 延迟加载路由

我们将从理解router-view标签需要嵌套开始。

router-view 标签需要嵌套

在我们开始之前,让我们看一下App.vue模板标签,如下所示:

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link :to="{ name: 'about' }">About</router-link> | 
      <router-link :to="{ name: 'cars' }">Cars</router-link>
    </div>
    <router-view />
  </div>
</template>

请注意,router-view元素(从底部数第三行)被包裹在父div标签内,然后再包裹在template标签内。这很重要,因为您不能将router-view标签直接放在template标签的子级。换句话说,以下是不可能的:

<template>
    <router-view />
</template>

现在我们知道这种方法行不通,我们可以继续讨论命名路由。

使用命名路由

要使用命名路由,只需将对象传递给router-link标签中的to属性,如下所示:

<router-link :to="{ name: 'about' }">About</router-link>

注意to属性前面的:。每当我们想要添加命名路由时,都会添加这个:

在传递给to属性的对象中使用name键,vue-router 将检查router.js中的routes数组。它将查找具有指定值的 name 键的对象,如果找到,它将重新路由到特定的视图组件。

通过触发 Vue 实例的方法导航到路由

Vue 中的每个组件都是一个独立的 Vue 实例。我们将在HelloWorld.vue组件中工作。要从HelloWorld.vuemethods选项中导航到路由,可以在组件的scripts部分中使用以下代码:

methods: {
 goToAboutPage(){ 
 this.$router.push({path: '/About'}) 
 },
}

为了使其工作,我们需要添加一个v-*指令来确定何时触发具有上述代码的方法。因此,在HelloWorld.vue中,仍然在template标签中更新为以下内容:

<template>
 <!-- code skipped for brevity -->
 <p v-on:mouseover="goToAboutPage" 
    style="color: red; font-size: 50px; background: gray; max-width: 500px; margin: 0 auto">
    Hover to see the About Page
 </p>
 <!-- code skipped for brevity -->
</template>

显然,上述template标签是不完整的。我们关注重要部分:文本颜色为红色,字体大小为50像素的p标签。你不能在屏幕上错过它!你可以在vuecli3chapter5/HelloWorld.vue中的第 4 行找到这行代码。

当你悬停在上面的段落时,Vue 会立即带你到关于页面。

现在让我们将主页上的相同功能添加到关于页面。因此,一旦你在关于页面上,你可以悬停在显眼的悬停上看到主页链接,它会带你回到主页。

为了使事情不那么跳跃,我们还可以使用老式的纯浏览器外观函数:setTimeout。以下是About.vue文件的更新代码:

<template>
  <div class="about">
    <h1>This is an about page. HMR rocks!</h1>
    <p v-on:mouseover="goToHomePageSlowly" class="go">Hover to see the Home Page</p>
  </div>
</template>
<script>
export default {
  name: "About",
  props: {
    msg: String
  },
  methods: {
      goToHomePage(){ 
        this.$router.push({path: '/'}) 
      },
      goToHomePageSlowly(){
        setTimeout(() => this.goToHomePage(), 1000);
      }
  }
};
</script>
<style>
.go {
  color: purple; 
  font-size: 50px; 
  cursor: pointer;
  max-width: 500px;
  margin: 0 auto;
  background: #fabdab;
}
</style>

在上述代码中我们在methods选项中简单地添加了另一个方法。我们给这个新方法命名为goToHomePageSlowly。然后,在我们的 about 组件的模板标签中调用这个方法。

goToHomePagesSlowly使用setTimeout外观函数来实现浏览器的setTimeout功能。setTimeout函数以1000毫秒的延迟调用我们的goToHomePage函数,一旦运行,它将使用$router返回到主页。

接下来,我们将讨论嵌套路由。

使用嵌套路由

在开始使用嵌套路由之前,我们将在src/views文件夹中添加 Cars 组件,如下所示:

<template>
  <div class="home">
    <HelloCars msg="Welcome to Your Cars" />
    <router-view></router-view>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloCars from "@/components/HelloCars.vue";

export default {
  name: "cars",
  components: {
    HelloCars
  }
};
</script>

要使用嵌套路由,您需要在router.js中的path对象中添加一个children数组,如下例所示:

routes: [
    {...},
    {...},
    {
      path: "/cars",
      name: "cars",
      component: Cars, 
      children: [
          { path: '/cars', component: CarsHome },
          { path: '/cars/cars-new', component: CarsNew },
          { path: '/cars/cars-used', component: CarsOld }
      ]
    }
]

每个子组件也需要路由。由于它们是嵌套路由,它们需要从各自的父组件中调用。在我们的情况下,这是HelloCars组件。我们将使用以下代码将HelloCars.vue组件添加到components文件夹中:

<template>
 <div class="hello">
 <h1>{{ msg }}</h1>
 </div>
</template>

<script>
export default {
 name: "HelloCars",
 props: {
 msg: String
 }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
* {
 margin: 0 auto;
}
</style>

现在我们只需要添加额外的子组件,我们的父组件HelloCars.vue将调用。

/cars路由可用的默认子组件是CarsHome.vue组件,如下所示:

<template>
  <div class="home">
    <div>
        This is Cars home
        <ul>
            <li><router-link to="/cars/cars-new">See new cars</router-link></li>
            <li><router-link to="/cars/cars-used">See old cars</router-link></li>
        </ul>
    </div>
  </div>
</template>

<style>
ul li { list-style-type: none }
</style>

如前所述,HelloCars.vue组件的一个子组件是CarsNew.vue组件,如下所示:

<template>
  <div>
    <div>
        This is Cars New
        <ul>
            <li><router-link to="/cars">Back to cars home</router-link></li>
        </ul> 
    </div>
  </div>
</template>

HelloCars.vue组件的另一个子组件是CarsOld.vue,如下所示:

<template>
  <div>
    <div>
        This is Cars Old
        <ul>
            <li><router-link to="/cars">Back to cars home</router-link></li>
        </ul> 
    </div>
  </div>
</template>

现在我们了解了嵌套路由的工作原理,我们将转移焦点,简要讨论懒加载路由。

懒加载路由

有时,webpack 生成的 JavaScript 包太大。这会减慢我们的 Web 应用程序加载时间,这当然是不可取的。

为了避免这种情况,我们可以回想一下 vue-router 的工作原理:每个路由都是一个单独的 Vue 组件。

我们已经在前面看到,webpack 在捆绑我们的 Vue 应用程序时会生成。这种行为可以用于我们的优势,使每个组件都捆绑到一个单独的块中。这是通过 Vue 的异步组件和 webpack 中的代码拆分实现的。

使用动态路由

什么是动态路由?让我们想象一个购物平台,在其中任何待售物品的 URL 结构都列在一个链接中,看起来像这样:

https://example.com/items/:id

:id部分是所谓的动态段。要使用动态段,您首先需要像任何其他路由一样在router.js中的路由对象数组中列出它们,如下所示:

routes: [
    {...},
    {...},
    {
        path: "/item/:id",
        name: "item",
        component: Item
    }
]

显然,在上述代码中,我们使用三个点来节省空间。

回到Item.vue视图组件的模板标签中,我们需要添加以下语法:

<template>
    <article>
        <h1>Shopping item: {{ $route.params.id }}</h1>
    </article>
</template>

我们活跃路由的状态存储在$route中。

至少可以单独撰写一整章关于动态路由,所以此时,我们需要继续讨论如何从 Vue 实例的methods选项中触发路由。

通过这个,我们结束了这一章。

总结

在这一章中,我们看了如何使用 vue-router 和 vuex 添加一个新的 Vue 项目。我们还通过 VS Code 的命令行配置了预设选项。我们讨论了 vue-router 的路由,并且学习了如何使用命名路由,添加动态路由,从 Vue 实例的方法选项导航到一个路由,并且处理嵌套(子)路由。

在下一章中,我们将看到如何在 Vue CLI 3 中使用 ESLint 和 Prettier。

第六章:在 Vue CLI 3 中使用 ESLint 和 Prettier

在本章中,我们将学习 ESLint 的用处,并看看如何使用它对我们的代码进行 lint。我们还将讨论不同的风格指南:标准、Airbnb 和 Google。具体来说,我们将看以下主题:

  • ESLint 是什么,以及如何单独配置它

  • 本地安装 npm 包和全局安装 npm 包之间的区别

  • 本地安装 ESLint 并使用 npx 运行它

  • 在 Vue CLI 3 中使用 ESLint

  • 使用 Vue CLI 3 UI 配置 ESLint

我们将首先看一下 ESLint 是什么,以及如何将其配置为一个独立的npm包。

ESLint 是什么,以及如何单独配置它

在本章中,我们将讨论 ESLint 的作用。ESLint 与代码质量有关。当你在一个团队中工作时,每个团队成员都会带来自己对于如何编写 JavaScript 的最佳方式的小怪癖和想法。即使你的团队对特定的编码风格和如何编写代码有明确的规则,你如何保证每个团队成员都遵守规则?你如何确保他们提供一致的代码质量?毕竟,我们都是人类,这意味着我们都有那些我们尽力了,但简单地忘记了要注意的小事情的日子。

在足够长的时间内,我们的团队将开始产生风格不一致的代码。接下来会发生的事情是,团队中的每个人开始将 JavaScript 风格指南视为建议,而不是你应该真正遵守的东西。

幸运的是,有一些工具可以让我们自动改善代码的外观,并在不遵循规定的做事方式时对其进行格式化。ESLint 就是这样一个工具的例子。

基本上,ESLint 是让你把制表符与空格等类似辩论外包给一款软件的方式,这款软件将以一种流畅、一致的方式处理这些问题。

在本章中,我们还将简要提到全局和本地 node 模块之间的区别,即全局安装npm包和本地安装之间的区别。

全局安装 npm 包与本地安装 npm 包的区别

这是一个全局安装的例子:

npm install eslint -g --verbose

这是一个本地安装的例子:

npm install eslint --save-dev --verbose

那么,有什么区别呢?

全局包安装在计算机的一个特定位置。无论您在安装它们时所在的文件夹是什么,它们都不会保存在该文件夹内,并且在命令行中全局可用。因此,如果我们想要从命令行运行一个包,全局安装是一种方法。

您可以从命令行程序中运行npm install命令。命令行程序将始终从一个目录内运行。使用诸如cd ..来在您的操作系统文件系统中返回上一级目录,或者cd <directory-name>来进入一个目录,您可以选择在安装npm包时希望您的命令行程序所在的文件夹。

npm包本地安装意味着该包保存在当前命令行程序指向的目录内。当运行npm install命令时,您正在安装的新包将保存在您所在的当前目录的node_modules目录中。如果node_modules目录不存在,当运行npm install命令时,它将被添加在当前目录内

使用全局模块的缺点是版本问题。对于本地模块,您计算机上的每个不同目录和每个不同应用程序都有自己的模块版本。然而,如果您有一个全局包,并决定更新它,全局安装的模块的更新版本可能会因为与特定目录中特定应用程序中其余代码的兼容性问题而破坏您的应用程序。

作为一个经验法则,应该将npm包安装在本地,因为可以避免版本问题。

要了解更多关于本地安装npm包的信息,请访问此网页:

docs.npmjs.com/downloading-and-installing-packages-locally.

使用本地安装的包的一个缺点是,特定命令,如prettierwebpackeslint,不会在命令行上可用。相反,您需要将本地安装的节点模块作为 npm 脚本运行。

或者,这个本地安装的模块实际上可以直接在命令行上运行,使用npx命令,我们将在下一节中讨论。

什么是 Prettier?

Prettier 是一个代码格式化工具。它会在你保存文件时格式化你的代码。该项目网站可以在prettier.io/找到。在接下来的示例中,我们将运行一个本地安装的 Prettier npm 模块。

使用 npx 在命令行上运行本地安装的 npm 模块

要开始使用 Prettier,我们将按照以下步骤启动一个新项目:

mkdir Chapter6 && cd $_

接下来,在新的Chapter6文件夹中,我们将添加另一个文件夹prettier-practice,如下所示:

mkdir prettier-practice && cd $_

接下来,我们将使用默认值初始化npm如下:

npm init -y

接下来,让我们添加一个单独的文件index.html,如下所示:

touch index.html && code .

上面的命令创建并打开了一个新的index.html文件在 VS Code 中。

我们将添加一个没有任何构建过程的小型 Vue 应用程序。让我们将以下代码添加到我们的index.html文件中:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>101 - using watchers in Vue</title>
    <style>
        body,
        input {
            font-family: Arial, sans-serif;
            font-size: 20px;
        }
    </style>
</head>

<body>
    <div id="example">
        <p>Enter owner name and the thing that is owned:
            <input v-model="ownerName" placeholder="enter owner">
            <input v-model="thing" placeholder="enter thing">
        </p>
        <span>{{ ownerName }}</span>
        <span> has a </span>
        <span>{{ thing }}</span>
    </div>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js'></script>
    <script>
        var example = new Vue({
            el: '#example',
            data: {
                ownerName: 'e.g Old McDonald',
                thing: 'e.g cow'
            },
            watch: {
                ownerName(currentValue, previousValue) {
console.log(`The value in the first input has changed from: ${previousValue} to: ${currentValue}`);
                }
            },
            computed: {
                // a computed getter
                ownerHasThing: function () {
                    // `this` points to the Vue instance's data option
                    return this.ownerName + " " + this.thing
                }
            }
        })
    </script>
</body>

</html>

你可以在 CodePen 上看到这个简单的 Vue 应用程序运行,网址是:codepen.io/AjdinImsirovic/pen/jprwKe.

接下来,让我们添加 Prettier 来看它如何格式化我们的代码。

全局安装 Prettier 并在 index.html 上运行

要全局安装 Prettier,我们可以使用以下命令:

npm install prettier -g --loglevel verbose

然后,要开始使用它,你可以运行--help标志来查看所有可用的选项,比如以下内容:

prettier --help

现在,你可以运行prettier index.html命令来在控制台中查看格式化后的代码。或者,你可以运行命令prettier index.html --write,这样格式化后的输出实际上会保存在你指定的文件中。

接下来,我们将看看如何在本地安装 Prettier 并使用 npx 运行它。

使用 npx 运行 Prettier

npx 实用程序是一个NPM 包运行器。它在 2017 年的 5.2.0 版本中被添加到 NPM 中。它使得从node_modules目录中运行包变得更容易,因为我们不必像之前在package.json中那样依赖于npm run <someScriptName>

在这个示例中,我们将看到如何将 Prettier 安装为开发依赖项,并如何使用 npx 运行它。首先,我们需要在我们的prettier-practice文件夹中使用--save-dev标志安装它,如下所示:

npm install prettier --save-dev --verbose

完成后,我们的package.json将会被更新,然后我们可以开始使用 Prettier。

最简单的方法就是在 VS Code 的终端中简单地运行 Prettier 命令。

要查看可用的选项,我们可以运行以下命令:

npx prettier

要实际运行带有一些选项的命令,我们可以运行这段代码:

npx prettier --single-quote --trailing-coma es5 --write "index.html" --verbose

npx 还有许多其他用法,这是一个值得熟悉的好工具。

另一个有趣的练习是比较 Prettier 的格式化和 VS Code 自带的格式化工具。使用Shift + Alt + F组合键可以触发 VS Code 的格式化工具。我们可以在 VS Code 的控制台中按上箭头键,快速重新运行刚刚运行的npx prettier命令。

接下来,我们将创建另一个小项目来演示如何使用 ESLint。

使用 ESLint

ESLint 是一个 JavaScript 的代码检查工具。你可以在eslint.org/找到它。代码检查工具会对你的代码进行分析,将其与特定的标准进行比较。你可以说它是一个检查代码质量的工具。代码检查工具非常适合团队环境,因为它们可以让我们的代码遵循特定的代码风格,并且确保在代码审查过程中少了一件需要讨论的事情。

代码风格的示例可以在这里找到:github.com/airbnb/javascript。这是 Airbnb 的 JavaScript 代码风格指南。如果你在页面上滚动,你会发现有很多需要阅读的信息:如何访问原始类型,如何重新分配引用,如何在对象声明中分组简写属性等等。

重要的是要理解 ESLint 只是分析你的代码;它不运行它。但是,它可以找到错误,并且也可以修复它们。实际上,如果设置正确,它可以改变你的代码。

还有其他一些 JavaScript 代码检查工具,比如 JSLint 或 JSHint。ESLint 被宣传为更加可定制的工具。

全局安装 ESLint 并在命令行中运行失败

要全局安装 ESLint 节点模块,请运行以下命令:

npm install eslint -g --loglevel verbose

现在,我们的eslint命令是全局可用的。

现在,我们将创建一个新的文件夹,eslint-practice。在其中,我们将创建一个新文件,eslint-test.js

在 VS Code 中打开文件并添加以下代码:

function (a) 
{
console.log(a, b);

}

保存文件。

接下来,在 VS Code 中使用Ctrl + `打开命令行,并运行以下命令:

eslint eslint-test.js

你将收到的输出是:

Oops! Something went wrong! :(

ESLint: 5.15.3.
ESLint couldn't find a configuration file. To set up a configuration file for this project, please run:

 eslint --init

ESLint looked for configuration files in C:\Users\Warrior Gaming\Desktop\Chapter6 and its ancestors. If it found none, it then looked in your home directory.

为什么会发生这种情况?没有 ESLint 配置文件,但为什么 ESLint 需要配置文件才能运行?

这是因为 ESLint 用来检查我们的代码的规则是在配置文件中指定的。如果没有配置文件,ESLint 就不知道在检查我们的代码时应用哪些规则。

这个问题的解决方案很有趣。没有package.json,我们就无法初始化 ESLint。因为我们必须安装一个新的 NPM 项目,我们可能会选择在本地安装 ESLint 节点模块。这不是必须的,但对于简化的工作流程来说,这是一个首选选项。

运行eslint --init命令

显然,我们不能在没有 ESLint 配置文件的情况下运行eslint命令。然而,我们也不能在没有package.json文件的情况下初始化 ESLint 配置文件。这意味着我们首先需要运行npm init,所以让我们现在这样做:

npm init -y

现在,我们可以初始化eslint。当我们运行eslint --init命令时,我们将在命令行提示中被问到几个问题。我们选择的答案将取决于我们的 ESLint 配置。以下是我们需要为这个示例选择的选项:

  • 选择To check syntax, find problems, and enforce code style

  • 选择None of these

  • 选择None of these(对于这个简单的演示,我们不会使用Vue.js,因为那将需要安装额外的依赖项,而在这一点上我们只是在测试 ESLint)

  • 选择Browser

  • 选择Answer questions about your style

  • 选择JSON

  • 选择Spaces

  • 选择Single

  • 选择Windows

  • 输入Y(是的,我们确实需要分号)

  • 选择''JavaScript''(作为你想要你的配置文件的格式是什么的答案)

一旦你回答了所有的问题,你将会看到以下输出:

Local ESLint installation not found. 
The config that you've selected requires the following dependencies:
eslint@latest
Successfully created .eslintrc.js file in C:\Users\W\Desktop\Chapter6\eslint-practice
ESLint was installed locally. We recommend using this local copy instead of your globally-installed copy.

阅读这条消息,我们现在可以欣赏到 ESLint 的维护者正在引导我们朝着在计算机上限制全局安装的npm包的最佳实践,并选择在我们的项目中本地安装我们的 node 模块。前面的消息还提到我们需要eslint@latest依赖项才能运行我们的 ESLint 配置,所以让我们立即添加它,如下所示:

npm install eslint@latest --save-dev --verbose

在本书中已经提到过,但现在是一个很好的复习时间:--save-dev标志意味着我们安装的包只用于开发,而不用于生产。--save-dev选项不会设置本地模块。你可以通过简单运行npm install estlint@latest来本地安装 ESLint。然而,--save-dev--verbose标志都有它们的用处,但需要明确的是它们与本地安装npm包没有任何关系。

现在,我们准备在项目的 JavaScript 文件上运行 ESLint。在这样做之前,让我们检查一下.eslintrc.js的内容。

理解 .eslintrc.js 配置文件的结构

根据我们选择的规则,我们生成的 .eslintrc.js 文件如下所示:

module.exports = {
    'env': {
        'browser': true,
        'es6': true
    },
    'extends': 'eslint:recommended',
    'globals': {
        'Atomics': 'readonly',
        'SharedArrayBuffer': 'readonly'
    },
    'parserOptions': {
        'ecmaVersion': 2018
    },
    'rules': {
        'indent': [
            'error',
            4
        ],
        'linebreak-style': [
            'error',
            'windows'
        ],
        'quotes': [
            'error',
            'single'
        ],
        'semi': [
            'error',
            'always'
        ]
    }
};

在配置文件中导出的对象内部,我们可以看到环境设置为 browseres6 属性设置为 true,这意味着 ES6 语法会自动启用。

通过 'extends': 'eslint:recommended',我们打开了推荐的核心规则,报告常见问题。这些规则列在以下页面上:eslint.org/docs/rules/

'globals' 条目列出了在使用指定配置运行 ESLint 时将访问的其他全局变量。

通过 parserOptions 属性,我们将 ECMA Script 版本设置为 2018,这当然是 ECMA Script 9。最后,'rules' 属性指定要应用的规则,以及错误级别

在 JavaScript 文件上运行 ESLint

现在,我们可以在 eslint-test.js 文件上运行 eslint 命令。由于它是全局安装的,我们可以简单地运行 eslint eslint-test.js

然而,由于这是被模块的维护者们不赞成的,让我们改为使用以下命令在本地运行它:

npx eslint eslint-test.js

运行上述命令将产生以下输出:

  1:10 error Parsing error: Unexpected token (

✖ 1 problem (1 error, 0 warnings)

我们还可以在 VS Code 中看到错误,作为一个单一字符,即 ( 字符,在我们的 eslint-test.js 文件的第一行下划线标记为波浪红色。当然,这个错误意味着我们缺少函数的名称。所以让我们更新代码为:

function  aFunction(a)  { console.log(a,  b)  }

注意,我们还删除了调用 console.log 方法后的分号。让我们再次运行 eslint

这一次我们得到了五个新的错误,如下所示:

  1:10 error 'aFunction' is defined but never used no-unused-vars
  3:1 error Expected indentation of 4 spaces but found 0 indent
  3:1 error Unexpected console statement no-console
  3:16 error 'b' is not defined no-undef
  3:18 error Missing semicolon semi

✖ 5 problems (5 errors, 0 warnings)
  2 errors and 0 warnings potentially fixable with the `--fix` option.

查看前述输出的每行末尾,我们可以看到我们的代码违反的具体ESLint 规则。在每行开头,我们可以看到行号,后跟一个冒号,再跟着违反 ESLint 规则的第一个字符的确切位置。因此,1:10 可以读作 第 1 行,第 10 个位置的字符

让我们再次运行 eslint,并使用建议的 --fix 标志,如下所示:

npx eslint eslint-test.js --fix

现在我们的代码被格式化,如下所示:

function aFunction(a) 
{
    console.log(a, b);

}

然而,我们仍然会得到一些错误,如下所示:

  1:10 error 'aFunction' is defined but never used no-unused-vars
  3:5 error Unexpected console statement no-console
  3:20 error 'b' is not defined no-undef

✖ 3 problems (3 errors, 0 warnings)

从这个小练习中我们可以得出结论,ESLint 将会执行以下操作:

  • 指出我们代码中的规则违反。

  • 允许我们传递 --fix 标志来纠正那些工具本身可以修复的错误。

接下来,我们将更新错误级别规则。

更新 ESLint 中的错误级别规则

默认情况下,所有规则的错误级别都设置为'error'。要手动设置不同的错误级别,比如'warn',我们可以添加一个errorLevel常量,并将我们的规则更新为以下代码:

const errorLevel1 = 'warn';
const errorLevel2 = 'error';
module.exports = {
    // ...
    // omitted this section to save space
    // ...
    'rules': {
        'indent': [
            'error',
            4
        ],
        'linebreak-style': [
            'error',
            'windows'
        ],
        'quotes': [
            'warn',
            'single'
        ],
        'semi': [
            'warn',
            'always'
        ]
    }
};

现在,通过这个更新,我们的linebreak-styleindent规则的错误级别将是error,而quotessemi规则的错误级别将是warn

接下来,我们将在 Vue CLI 3 中使用 ESLint。

在 Vue CLI 3 中配置 ESLint

现在我们已经熟悉了 Prettier 和 ESLint,我们将在 Vue CLI 3 中将它们安装到一个新项目中。让我们将 Git Bash 指向Chapter6文件夹的根目录,并运行以下命令:

code .

一旦 VS Code 打开,我们将切换到命令行,并运行以下命令:

vue create vc3-prettier-eslint

然后,我们将接受使用 Babel 和 ESLint 的默认安装,并等待应用程序安装完成。

接下来,类似于之前的操作,我们将运行vue ui,然后将vc3-eslint应用程序导入到我们的 Vue CLI 3 GUI 仪表板中。

正如我们所看到的,ESLint 作为 Vue CLI 3 应用的默认安装。但是,我们如何配置 ESLint,就像我们在本章的前一节中所做的那样呢?

在 Vue CLI 3 GUI 中设置 ESLint 配置

在 Vue CLI 3 UI 中加载我们的vc3-eslint应用程序后,让我们单击配置图标。

我们将单击 ESLint 配置,这将更新项目配置窗口右侧的面板,如下所示:

图 6.1:单击配置图标显示应用程序的可能配置

在这个视图中,我们可以看到两个主要条目:保存时进行 Lint 和选择配置。

保存时进行 Lint 选项目前已经切换打开,但我们可以通过单击 Lint on save 选项右侧的绿色开关来切换关闭。

我们还可以在“选择配置”条目中选择不同的配置。默认设置可以更改为“强烈推荐”或“推荐”设置。我们在本章前面看到了如何在eslintrc.js文件中配置此设置。

您还可以选择点击页面右上角的“打开 eslintrc”按钮,打开我们项目的 ESLint 配置文件,这样您就可以直接编辑它。

最后,我们可以通过单击配置面板顶部的“规则”选项卡,查看项目中所有 ESLint 规则的列表,如下所示:

图 6.2:在 Vue CLI 3 UI 中选择 ESLint 配置屏幕中的单个规则

屏幕将显示默认应用于我们 ESLint 配置的基本规则,而在“常规”选项卡上,我们可以通过单击“选择配置条目”中的下拉菜单来更改整个规则集;在规则选项卡中,我们可以混合和匹配单个规则,然后保存我们的更新。这样就可以更新规则并根据自己的喜好进行自定义更改。

在 Vue CLI 3 UI 项目中同时使用 ESLint 和 Prettier

如果您在 Vue CLI 3 UI 中从头开始一个项目,您也可以让 ESLint 和 Prettier 一起工作。方法如下:

  1. 我们首先要将 Vue UI 指向根文件夹,如下所示。重要的是要验证您不在现有的 Vue 应用程序内:

图 6.3:在 Vue CLI 3 UI 中创建新项目

  1. 接下来,我们将点击“选择此文件夹”按钮继续,然后按照以下方式选择我们项目的名称:

图 6.4:添加项目名称

  1. 接下来,我们将点击“选择此文件夹”按钮继续,然后选择我们项目的名称。点击“下一步”继续,您将被带到预设选项卡。

  2. 一旦您在预设选项卡上,选择手动预设以手动选择功能,然后再次点击“下一步”。在功能选项卡上,Babel 和代码检查/格式化功能应该已经被预先选择,所以只需再次点击“下一步”进入配置屏幕,如下所示:

图 6.5:从配置屏幕中选择 ESLint + Prettier

  1. “选择一个代码检查/格式化配置”给了我们几个选项。在底部选择ESLint + Prettier。一旦我们点击它,就会出现一个选项来保存预设,所以让我们按照以下图片保存它:

图 6.6:在 Vue CLI 3 UI 中保存新预设

  1. 一旦我们点击“创建新预设”按钮,我们就完成了对项目的自定义,然后我们可以等待所有依赖项安装完成。

  2. 完成后,您将看到“欢迎使用新项目”的消息。现在,您可以点击左侧菜单上的“项目依赖”链接。除了预期的依赖项(babel-eslinteslinteslint-plugin-vuevue-template-compiler)之外,您还会看到@vue/eslint-config-prettier开发依赖项。正如我们所看到的,这是一个官方的vue npm模块,因为它有@vue命名空间。

总结

在本章中,我们已经看到了npmnpx、全局和本地安装节点模块之间的区别。我们进一步讨论了 ESLint 和 Prettier。我们看到了如何在独立项目中安装它们,以及如何在 Vue CLI 3 GUI 中配置 ESLint。我们还看到了如何在 Vue CLI 3 中设置 ESLint 和 Prettier。

在下一章中,我们将探讨在 Vue CLI 3 中使用 CSS、SCSS 和 PostCSS。

第七章:使用 SCSS 改进 CSS

在本章中,我们将讨论 SCSS 的基础知识以及它解决的问题。我们还将讨论引入的改进,使 CSS 更接近 SCSS。

我们还将使用我们在第五章中制作的应用程序,Vue CLI 3 和路由*。本章的目标是使用 CSS、SCSS,并通过使用 Bootstrap + Vue 插件来实现这一目标。

本章将涵盖以下主题:

  • 安装 Bootstrap + Vue

  • 使用 bootstrap-vue 插件为我们的项目添加样式

  • 在我们的项目中使用 SCSS

安装 Bootstrap + Vue

在使用 Vue 时,为什么不从官方网站使用 Bootstrap?嗯,我们当然可以这样做,但 Bootstrap 依赖于 jQuery,而且由于我们希望将所有与 JavaScript 相关的内容都通过 Vue 运行,因此我们必须使用一个专为此目的构建的项目:BootstrapVue。

让我们从访问项目网站开始bootstrap-vue.js.org/。在这里,我们可以对项目有一个大致的了解。具体来说,阅读文档bootstrap-vue.js.org/docs#vue-cli-3将非常有用,该文档讨论了在 Vue CLI 3 项目中使用 BootstrapVue。

将 BootstrapVue 添加为插件

您可以通过 Vue CLI 3 UI 的帮助轻松创建一个新的 Vue 项目。这在本书中已经多次介绍过,您应该能够自己完成这个操作。

将您的新项目命名为“第七章”,并按照与第五章相同的安装步骤运行它,Vue CLI 3 和路由*。

在控制台中,转到项目的根目录并运行以下命令:

vue add bootstrap-vue

您将在控制台内看到以下提示:

Successfully installed plugin: vue-cli-plugin-bootstrap-vue

接下来将跟进以下问题:

? Use babel/polyfill? (Y/n)

只需按下Enter键接受默认答案(是)。

无论您如何安装插件,您的插件列表现在应该是这样的:

既然我们已经安装了它,我们可以开始使用它了。

使用 bootstrap-vue 插件为我们的项目添加样式

安装了bootstrap-vue插件后,让我们在项目中使用它!我们将从官方文档中添加一个navbar,该文档可在bootstrap-vue.js.org/docs/components/navbar#b-nav-item-dropdown找到,如下所示:

  <b-navbar type="dark" variant="dark">
    <b-navbar-nav>
      <b-nav-item href="#">Home</b-nav-item>

      <!-- Navbar dropdowns -->
      <b-nav-item-dropdown text="Lang" right>
        <b-dropdown-item href="#">EN</b-dropdown-item>
        <b-dropdown-item href="#">ES</b-dropdown-item>
        <b-dropdown-item href="#">RU</b-dropdown-item>
        <b-dropdown-item href="#">FA</b-dropdown-item>
      </b-nav-item-dropdown>

      <b-nav-item-dropdown text="User" right>
        <b-dropdown-item href="#">Account</b-dropdown-item>
        <b-dropdown-item href="#">Settings</b-dropdown-item>
      </b-nav-item-dropdown>
    </b-navbar-nav>
  </b-navbar>

我们将在App.vue中的模板部分添加这个navbar。更新后的template元素现在看起来是这样的:

<template>
  <div id="app">
    <div id="nav">

      <b-navbar type="dark" variant="secondary">
        <b-navbar-nav>
          <b-nav-item href="#">Home</b-nav-item>
          <!-- Navbar dropdowns -->
          <b-nav-item-dropdown text="Lang" right>
            <b-dropdown-item href="#">EN</b-dropdown-item>
            <b-dropdown-item href="#">ES</b-dropdown-item>
            <b-dropdown-item href="#">RU</b-dropdown-item>
            <b-dropdown-item href="#">FA</b-dropdown-item>
          </b-nav-item-dropdown>

          <b-nav-item-dropdown text="User" right>
            <b-dropdown-item href="#">Account</b-dropdown-item>
            <b-dropdown-item href="#">Settings</b-dropdown-item>
          </b-nav-item-dropdown>
        </b-navbar-nav>
      </b-navbar>
      <!--
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
      -->
    </div>
    <router-view />
  </div>
</template>

我们还需要更新样式,使其看起来像这样:

<style>
#app {
  text-align: center;
  color: #2c3e50;
}

#nav a {
  font-weight: bold;
  color: #2c3e50;
}

#nav a.router-link-exact-active {
  color: #42b983;
}
</style>

保存更改后,我们的主页将更新为以下截图:

要快速更改bootstrap-vue navbar的背景颜色,只需将 Bootstrap 颜色添加到variant自定义 HTML 属性中。接受的值为primarysecondarysuccessdangerinfowarninglightdark

在前面的例子中,我们使用了值为secondaryvariant,这给了我们一个灰色的背景,鼠标悬停时显示白色的nav项。

在我们的项目中使用 SCSS

类似于 TypeScript 被称为 JavaScript 的超集,SCSS 经常被称为 CSS 的超集。但这个超集到底是什么?

语言的超集只是它周围的一个层,具有在常规实现中不存在的附加功能。还可能有额外的最佳实践、方法等。

在最核心的层面,SCSS 文件可能只包含普通的 CSS 语法。这是因为所有的 SCSS 最终都会编译成 CSS,并且作为这样,它会被提供给我们的浏览器。这使得它非常易于接近。对于 SCSS 新手来说,了解他们可以继续编写 CSS 并且它会在他们的 SCSS 中正常工作是令人放心的!

让我们把这作为我们的起点。首先,让我们更新我们的bootstrap-vue插件设置,以便我们使用 SCSS 而不是 CSS。

导航到我们应用程序的文件夹结构,并找到以下文件:src/plugins/bootstrap-vue.js。接下来,更新代码,使其看起来像下面这样:

import Vue from 'vue'

import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/scss/bootstrap.scss'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.use(BootstrapVue)

处理错误

可能会遇到“找不到 sass-loader”错误。您可以通过运行以下命令来解决它:

npm install -D sass-loader sass

此时,如果您不确定加载程序是什么,可能值得重新阅读第二章,Vue CLI 3 中的 Webpack,以便对 webpack 加载程序进行复习。

可能会出现的另一个错误是:

Module build failed (from ./node_modules/sass-loader/lib/loader.js): Error: Cannot find module 'node-sass'

你可以通过运行以下命令来解决这个错误:

npm install node-sass

最后,在安装新包之后,你会看到一条消息,上面写着found 1 high severity vulnerability(或类似的内容)。你可以,也应该,根据控制台的提示修复这样的漏洞,并运行npm audit fix

在我们的项目中编写一些 SCSS

现在我们已经导入了bootstrap.scss,我们可以开始使用它了。

让我们打开App.vue,并将style标签更新为以下内容:

<style lang="scss">
#app {
  text-align: center;
  color: #2c3e50;
}

#nav {
  a {
    font-weight: bold;
  }
  a.router-link-exact-active {
    color: #42b983;
  }
}
</style>

在上面的代码中,我们看到了嵌套的例子,这是 SCSS 的一个特性,它允许我们在 SCSS 规则内模仿我们应用程序的 HTML 结构。

如果你在这个阶段查看你的项目在网页浏览器中的运行情况,你会注意到它仍在运行,并且没有改变。这是好的!这意味着一切都在正常工作,一切都得到了应有的服务。

现在让我们在我们的 SCSS 中添加一些变量、混合和插值。

覆盖 bootstrap-vue 样式

我们将首先添加一个自定义的 SCSS 文件。我们将把它命名为custom.scss,并将其放在项目的assets文件夹中。

现在让我们把这段代码添加到custom.scss中:

$secondary: tomato;

我们刚刚覆盖了 Bootstrap 的变量。现在让我们在App.vue文件中使用它,通过导入custom.scss文件。我们还将在#nav元素内覆盖.bg-secondary类。更新后的script标签将如下所示:

<style lang="scss">
@import './assets/custom.scss';
#app {
  text-align: center;
  color: #2c3e50;
}

#nav {
  a {
    font-weight: bold;
  }
  a.router-link-exact-active {
    color: #42b983;
  }
  .bg-secondary {
    background-color: $secondary;
  }
}
</style>

在我们保存了所有的更改之后,我们的项目将更新为如下所示:

接下来,我们将在App.vue文件中使用一些更高级的 SCSS 特性。

使用变量、混合和插值

在这一部分,我们将在 SCSS 中使用一些更多的变量、混合和插值语法。在我们开始本章之前,有必要提到一个网站,你可以在这个网站上练习编写 SCSS,并查看它生成的 CSS 输出。这个网站叫做 Sassmeister,网址是:www.sassmeister.com/

使用 Sassmeister 练习 SCSS

一旦你访问了这个网站,你可以通过悬停在选项上来选择你想使用的 Sass 或 SCSS 的风格,如下所示:

Sassmeister 网站是一个练习使用语言各种特性的好地方。例如,我们可以导航到我们项目的node_modules文件夹,并找到bootstrap文件夹。

如果您在node_modules中找不到 bootstrap 文件夹,可以使用npm i bootstrap进行安装。

接下来,打开scss/mixins文件夹,找到_alert.scss,其语法如下:

@mixin alert-variant($background, $border, $color) {
  color: $color;
  @include gradient-bg($background);
  border-color: $border;

  hr {
    border-top-color: darken($border, 5%);
  }

  .alert-link {
    color: darken($color, 10%);
  }
}

正如我们所看到的,这是一个 mixin。让我们将其复制粘贴到 Sassmeister 中,看看我们得到什么输出。

实际上,我们不会得到任何输出。为什么呢?

原因很简单:在 Sass 或 SCSS 中的 mixin 实际上就像是其他语言中的函数,例如 JavaScript。因此,要在 SCSS 中使用 mixin,我们需要调用它,并传递一些参数。这里是一个例子:

@include alert-variant(tomato, purple, white);

请注意,使用@include语法是运行 mixin 所必需的。

上述代码应该可以工作,但在我们的 mixin 定义内部,我们调用另一个 mixin,如下所示:

@include gradient-bg($background);

这意味着为了使我们的代码在 Sassmeister 中编译,我们需要用其他内容替换上述行,例如,用以下内容:

background: $background;

最后,我们的@include for alert-custom,需要应用于 CSS 规则。这意味着我们需要用 CSS 声明包装我们对alert-custom的调用,就像下面的例子一样:

.alert-custom {
  @include alert-variant(tomato, purple, white);
}

将所有这些放在一起,这是我们的 SCSS 代码:

@mixin alert-variant($background, $border, $color) {
  color: $color;
  background: $background;
  border-color: $border;

  hr {
    border-top-color: darken($border, 5%);
  }

  .alert-link {
    color: darken($color, 10%);
  }
}
.alert-custom {
  @include alert-variant(tomato, purple, white);
}

Sassmeister 将把上述代码编译为以下内容:

.alert-custom {
  color: white;
  background: tomato;
  border-color: purple;
}

.alert-custom hr {
  border-top-color: #670067;
}

.alert-custom .alert-link {
  color: #e6e6e6;
}

既然我们知道如何使用 SCSS mixins,我们可以在我们的项目中使用它们。

在我们的 Vue 项目中使用 SCSS mixins 和插值

我们将从在App.vue中添加一个警报开始,如下所示:

<b-alert show>Default Alert</b-alert>

这个简单的添加将更新我们的应用程序外观为这样:

现在我们将添加一些 mixins 来更新样式。

我们将从添加我们的自定义 mixin 开始,以给我们添加的警报上色。以下是custom.scss的代码:

$secondary: tomato!important;
$border: darken(#ff0000, 10%);

@mixin alert-variant($background, $border, $color) {
    color: $color;
    background: $background;
    border-color: $border;
    border-radius: 0;
    border-width: 5px;

    .alert-link {
      color: darken($color, 10%);
    }
  }
  .alert-info {
    @include alert-variant(rgb(255, 192, 181), #ff0000, white);
  }

保存上述文件后,我们的警报将如下所示:

有了这个,我们结束本章。

摘要

SCSS 是一个庞大的主题。在像 Vue 这样的 VDOM 框架中使用 SCSS 可能会变得复杂,因为涉及的概念数量很多。本章为您提供了可用的内容以及如何入门的一瞥。

在本章中,我们已经涉及了在我们的项目中使用 SCSS。我们已经了解了如何在我们的 Vue 应用程序中使用 CSS 和 SCSS。我们还了解了 SCSS 的一些主要特性,如变量、mixins 和插值,还学会了如何在我们的 Vue 应用程序中实现 Bootstrap 4。接下来,我们学会了如何编辑 Vue 中 bootstrap-vue 插件的内置组件,并如何使用自定义 SCSS 代码对其进行更新。

在下一章中,我们将使用到目前为止学到的所有知识来构建一个简单的项目,并将其发布在 GitHub Pages 上。

第八章:在 GitHub Pages 上部署 Vue CLI 3 应用

在本章中,我们将在一个新的 GitHub 账户上设置一个新的仓库,并快速原型化一个 Vue 项目。然后,我们将使用 GitHub Pages 进行部署。在本章中,我们将熟悉以下内容:

  • GitHub 桌面应用

  • Git 的基础知识(它是什么以及它是如何工作的)

  • 一些基本的 Git 命令

  • 理解 Git 中的分支

  • 如何正确设置 Vue 应用以在 GitHub Pages 上工作

在本章结束时,你将拥有一个在 GitHub Pages 上运行的完全可用的 Vue 应用。让我们从理解如何使用 GitHub 桌面应用开始。

安装 GitHub 桌面应用

首先,转到以下 URL:https://desktop.github.com。接下来,只需通过屏幕中央醒目的下载按钮下载应用,如下截图所示:

一旦你下载了 GitHub 桌面应用的安装文件(GithubDesktopSetup.exe),你需要运行安装。

安装完成后,你会看到一个简洁的界面。如果你第一次使用 Git 和 GitHub,这个简洁的界面可能看起来几乎是太简洁了。这个应用到底是怎么回事?

为了理解这个应用是如何工作的,你需要了解一些 Git 的基本概念。

理解 Git 的工作原理

在你工作在一个项目上时,如果你没有使用像 Git 这样的源代码版本控制,你可能会认为你的项目只有一个文件夹。例如,使用 Vue CLI 3 安装的任何 Vue 应用都会以一个单独的文件夹的形式存在,里面包含了一些子文件夹。

我们可以简化这样一个 Vue 应用的树形结构,并描述它如下:

aVueApp
   |- aSubfolder
   |- anotherSubfolder
   |- yetAnotherSubfolder

请注意,我们想象中的 Vue 应用有一个名为aVueApp的根文件夹。在这个根文件夹里有三个子文件夹,包含了我们 Vue 应用的完整功能。

只要我们只处理一些文件和文件夹,也就是说,只要我们的 Vue 应用非常小,我们就不必担心对文件和文件夹进行版本控制,因为几乎没有什么需要进行版本控制的。如果我们在一个文件或文件夹中犯了错误,我们只需撤消更改,就可以回到文件的早期版本。这是一个合理的方法。

然而,如果我们的项目增长到,比如说,30 个文件分布在七个文件夹中,会发生什么呢?让我们再想象一下,在开发 Vue 项目期间,我们只更新了这 30 个文件中的几行代码。让我们进一步想象,我们对这些文件做了很多更改,并且在开发过程中犯了一些重大错误,以至于我们根本无法继续在我们的项目上工作。通常,在一个较小的项目上,我们可以简单地撤消我们对几个文件所做的更改,以回到我们应用程序的上一个工作版本

然而,由于许多更改分布在许多不同的文件中,我们不仅不太可能记得撤消每个更改以回到我们应用程序的上一个工作版本,而且撤消所有这些更改也会耗费时间,因此最终是不切实际的。

开发者该怎么办呢?

幸运的是,我们有版本控制。Git 被称为分布式版本控制系统。不用太技术化地说,你可以把 Git 想象成一个大的撤销/重做按钮,只是有一个小小的附带条件。Git 不是在单个文件上撤消更改,而是通过时间跟踪开发者应用程序的版本,有点像在某个时间点对整个应用程序进行快照。

开发者负责决定何时进行这个过程。例如,当你在应用程序中编写了一个新功能,并且准备保存应用程序的当前状态以便以后回到它时,你只需通过提交更改来保存它。

与其在理论上描述这个过程,不如开始一个新的 Vue 应用程序,并借助 Git 跟踪对其所做的更改。

开始一个新的 Vue 应用程序,并使用 Git 跟踪更改

让我们打开 Git Bash,并按照以下步骤在我们选择的文件夹中创建一个新的 Vue 项目:

vue create chapter8

让我们保持简单,每当 Vue CLI 3 提示我们回答时,按下Enter键。正如我们已经学到的,这是在使用 Vue CLI 3 安装新的 Vue 应用程序时接受默认设置的快速简便方法。

要开始使用 Git 跟踪项目,我们运行以下命令:

git init

这个命令初始化了一个新的本地 Git 仓库。我们在这里使用“本地”这个词,因为目前,这个仓库只存在于我们的计算机上。如果明天我们抹掉了计算机的磁盘,我们刚刚创建的本地 Git 仓库也会丢失。

然而,有些情况下 Git 仓库已经被初始化。以下是一个简单的命令,我们可以运行来查看我们的项目中是否有 Git 仓库:

git status

上面的命令为我们提供了有关我们仓库当前状态的信息。如果我们运行此命令的文件夹不为空,它将报告当前文件夹不是一个 Git 仓库。

现在让我们在chapter8文件夹的根目录运行git status命令。这是我们得到的内容:

On branch master
nothing to commit, working tree clean

这些信息告诉我们,我们目前正在项目的主分支上,并且没有要提交的内容。工作树是干净的。这个工作树是什么?

工作树代表了在我们项目中保存并已提交更改的所有文件和文件夹。

要检查对我们项目文件所做更改的历史记录,我们可以运行这个命令:

git log

这个命令将列出到目前为止我们添加到项目中的所有提交。以下是上一个命令的输出:

commit ee07b4828fb217902f2f7c1047f00f936c3a461f (HEAD -> master)
Author: UserWithEmail <[email protected]>
Date: Mon Apr 22 22:18:48 2019 +0200

 init

在这里,我们可以看到几条信息:

  • 用一个包含 40 个字符的 SHA 唯一标识符进行提交

  • 提交作者(包括作者的用户名和电子邮件地址)

  • 提交时的日期和时间

现在让我们对App.vue文件进行一个小的更改。我们将把msg属性从 Welcome to Your Vue.js App 更新为只是 Welcome。一旦我们保存了更改,我们可以再次运行git status命令。这是我们将在控制台中得到的内容:

On branch master
Changes not staged for commit:
 (use ''git add <file>...'' to update what will be committed)
 (use ''git checkout -- <file>...'' to discard changes in working directory)

 modified: src/App.vue
no changes added to commit (use ''git add'' and/or ''git commit -a'')

现在,我们可以创建应用程序在这个时间点的另一个快照。为此,我们需要做以下两件事:

  • 首先,我们需要将所有更改添加到暂存区(这是第二个 Git 树)。

  • 其次,我们需要提交这些更改,以便它们获得自己的提交 SHA(由 40 个伪随机字符组成的唯一标识符)。

提交更改到我们的应用程序

让我们用这个命令添加所有的更改:

git add --all

接下来,我们将通过给出提交消息来提交更改,如下所示:

git commit -m "Update App.vue's template"

现在,让我们再次运行git log命令来查看输出。这一次,我们还将传递一个标志,--oneline,如下所示:

git log --oneline

这是我们在控制台中得到的结果:

e469374 (HEAD -> master) Update App.vue's template
ee07b48 init

请注意,这一次,我们得到的信息要简洁得多。40 个字符的 SHA 字符串现在被缩写为前八个字母和数字,并且作者的详细信息被省略了。--oneline标志在我们需要查看许多提交时非常有用。您甚至可以通过传递另一个标志来缩小结果的数量,以减少要查看的提交数量。无论您指定的数字是多少,您都将得到最近提交的这么多个。

例如,我们目前有两个提交,所以我们可以运行这个命令来查看最后两个提交:

git log --oneline -2

我们也可以运行这个命令来只查看最后一次提交:

git log --oneline -1

接下来,我们将看看三棵树的概念。

三棵树的概念

Git 中有三棵树的概念。重要的是要注意,这个概念与树数据结构无关。在这里,树只是一个我们用来指代文件某种状态的比喻。这三棵树包括以下内容:

  • 工作目录

  • 暂存区(也称为暂存索引)

  • 存储库

三棵树的概念可能一开始听起来很混乱,但实际上非常简单。以下是一个基本的 Git 工作流程:

  1. 我们使用vue create <appname>来安装一个应用程序。

  2. 作为安装的一部分,我们的应用程序被初始化为一个 Git 存储库。

  3. 安装完成后,我们拥有了所有的文件(工作目录)和一个单独的提交(带有消息“init”,表示已初始化存储库)。

  4. 然后,我们对工作目录进行了一些更改。

  5. 在提交这些更改之前,我们需要将它们添加到我们的暂存索引中。暂存索引只是一棵准备提交的更新文件的树。如果我们没有使用git add <filename>命令添加任何文件,我们的暂存索引就是空的。

  6. 当您将所有文件暂存到暂存区后,然后提交它们(使用git commit -m语法,后面跟着引号内的特定提交消息)。

  7. 当您提交了更改后,您只需重复这个过程。

除了工作目录和暂存区,第三棵树就是存储库。您可以使用checkout命令来加载存储库中的任何部分到您的工作目录中。然后,如果需要,您可以简单地重复这个过程。

Git 中的分支

Git 中的另一个重要概念是分支。对于科幻小说迷来说,分支可以被描述为一种多元宇宙:一个项目可以在其中有一个底部导航栏,或者根本没有导航栏。

当我们想要向项目中添加一个新功能时,我们使用分支。这样,每个分支代表项目的一个单独功能。

每个 Git 项目都从一个单一分支开始:master。

一旦我们决定需要另一个分支来处理特殊功能,我们只需运行以下命令:

git checkout -b "branch name here"

上面的命令意味着:创建一个新分支,称之为分支名称,并切换到这个新添加的分支。

要查看我们项目中所有分支的列表,我们只需运行以下命令:

git branch

这个命令将打印出我们项目中所有的分支,并在当前分支前面放一个星号。以下是一个示例输出:

branch one
branch two
* master

上面的输出意味着我们的项目中总共有三个分支,我们当前位于master分支上。

合并分支

在我们在 GitHub 中设置项目之前,还有一件事要提到,那就是合并分支的概念。

工作流程如下:我们使用一个合理的名称(例如add-navbar)检出一个新分支。接下来,我们将所有想要的功能添加到这个分支,并提交我们的更改。完成后,我们切换回另一个分支,例如master。然后我们只需运行以下命令:

git merge add-navbar

这样做将导致add-navbar分支中的所有代码被合并到master分支中。我们的master分支和add-navbar分支现在共享相同的代码。

请注意,如果你的工作目录中有未提交的更改,你不能切换分支!如果你不想提交你的更改,但仍然需要切换到另一个分支,一个解决方法是使用git stash命令。

这就结束了我们对 Git 一些基本概念的快速介绍。然而,这远远不是一个完整的介绍。我们只是提到了一些我们将在项目中使用的基本功能。还有很多东西要学习。

注册一个新的 GitHub 账户

我们已经安装了 GitHub 桌面版。我们对 Git 也有足够的了解,能够理解本章节的其余内容。现在我们将注册一个 GitHub 账户。

导航到github.com并注册一个新账户。确保检查你的电子邮件并确认注册。

一旦您注册并登录,您将看到这样的界面:

这是我们的远程GitHub 存储库将位于的位置。要添加到我们的远程存储库,我们需要将更改推送到那里。远程存储库被称为origin/master

幸运的是,我们已经安装了 GitHub 桌面,并且使用它是与 GitHub 交互的最简单的方式。您可以轻松创建新存储库,更新现有存储库,添加分支,并从 GitHub 桌面推送到远程存储库。

我们已经有了chapter8 Vue项目,并向其添加了一个提交。现在让我们使用 GitHub 桌面将其添加到远程。

使用 GitHub 桌面添加 origin/master

让我们打开 GitHub 桌面应用程序。我们将通过添加我们的chapter8项目开始使用它。要做到这一点,请单击主应用程序菜单顶部的文件下拉菜单。接下来,单击“添加本地存储库”命令。

将会出现一个弹出窗口。此弹出窗口的标题是“添加本地存储库”。在弹出窗口的正文中,我们可以看到一个带有占位符“存储库路径”的单个输入字段。旁边是选择本地存储库的按钮。让我们单击“选择...”按钮。

单击“选择...”按钮将打开 Windows 资源管理器,我们可以导航到chapter8文件夹的位置。一旦选择了chapter8文件夹,只需单击 Windows 资源管理器窗口底部的“选择文件夹”按钮。

接下来,只需按照以下弹出窗口中的“添加存储库”按钮:

就是这样!您刚刚添加了您的本地存储库。现在,您已经准备好发布它了。

发布您的本地存储库

要发布我们的本地存储库,我们只需单击“发布存储库”按钮,如下所示:

单击“发布存储库”按钮后,将会出现一个新的弹出窗口。在“发布存储库”弹出窗口中已经添加了以下默认设置:

  • 存储库名称(在 GitHub 中显示的名称)

  • 描述(默认为空)

  • 保持此代码私有复选框(已选中)

让我们接受默认设置并单击“发布存储库”按钮。我们现在在 GitHub 帐户中将有一个新的私有存储库。

回到 GitHub,这是我们的远程存储库:

如果我们单击左侧边栏中的chapter8链接,我们将被带到我们的存储库,如下所示:

在这里,我们可以看到整个项目。

我们还可以看到我们的存储库中目前有 2 次提交。单击“2 次提交”链接将带我们进入一种提交的可视 Git 日志,您还可以单击每个单独的提交以检查在项目历史的特定时间所做的更改。

接下来,我们将发布我们的项目,以便在 GitHub Pages 上看到。

在 GitHub Pages 上发布我们的项目

GitHub Pages 是一个托管服务。您可以在那里托管静态文件。这意味着您不能托管带有后端数据库的项目,因此使用后端技术编写的项目,如 PHP、Node、.NET 等,无法添加。

不过,一个由静态文件组成的简单项目可以走得很远,这是很有趣的。您甚至可以使用 Jekyll 来托管博客,这是 GitHub 的无服务器博客平台。

然而,本节的重点是发布我们的简单 Vue 应用程序,所以让我们准备好做到这一点。

准备好发布我们的项目

我们将从 GitHub 上的存储库仪表板开始。让我们按照以下步骤导航到“设置”选项卡:

接下来,我们需要向下滚动到 GitHub Pages 部分,如下所示:

从前面的屏幕截图中,我们可以看到我们需要在将存储库公开之前才能在 GitHub Pages 上发布。为此,我们只需点击“使公开”按钮(在“危险区域”标题下的第一个按钮)如下所示:

在弹出窗口中,我们将输入我们的存储库名称以确认我们的选择,然后点击“我明白,使此存储库公开”按钮。GitHub 可能会要求您在此阶段重新输入密码。

现在,您需要再次向下滚动到 GitHub Pages 部分,并单击下拉按钮。在下拉列表中选择主分支,如下所示:

一旦您选择了主分支,在主菜单下会出现一个警报,上面会显示“GitHub Pages 源已保存”,如下所示:

最后,再次向下滚动到 GitHub Pages 部分,您将看到此消息:

一切都已准备就绪,可以在 GitHub Pages 上发布,但我们仍然需要配置我们的 Vue 应用程序。

更新 Vue 配置文件

在本书中看到的所有配置文件中,Vue 本身也有一个!这个文件的名称是vue.config.js,它位于我们项目的根目录中。这个文件是可选的,所以vue.config.js不是我们项目预安装的。让我们将其添加到我们项目的根目录,并向其中添加以下代码:

// vue.config.js
module.exports = {
  // options...
}

我们将给我们的 Vue 配置文件的第一个选项是publicPath,如下所示:

module.exports = {
  publicPath: process.env.NODE_ENV === 'production'
    ? '/chapter8/'
    : '/'
}

您可以在以下网址阅读更多关于此设置的信息:cli.vuejs.org/guide/deployment.html#github-pages

让我们保存我们的更改,并使用 GitHub Desktop 将它们提交并推送到远程存储库。

保存更改并使用 GitHub Desktop 将它们推送到远程存储库

打开 GitHub Desktop,您将看到列出您的更改。只需在应用程序的左下角键入提交消息,然后单击提交到主按钮(GitHub Desktop 应用程序的左下角的蓝色按钮,如下面的屏幕截图所示):

一旦您点击提交到主按钮,您需要将更改推送到 origin(远程存储库的另一个名称),如下所示:

不幸的是,我们的存储库仍然不会被发布。要发布它,我们需要打开我们根目录中的.gitignore文件,并注释掉/dist文件夹,以便它不再被忽略,如下所示:

.DS_Store
node_modules
#/dist

接下来,我们将使用以下命令构建我们的项目:

npm run build

我们将看到以下消息:

Build deployed. The dist directory is ready to be deployed.

在 GitHub Desktop 中提交更改并附上消息,例如:准备 dist 目录。之后,像以前一样,点击 Push origin 按钮。

调试您的 GitHub 页面部署

有时,事情就是不像它们应该的那样工作。在这种情况下,您可以简单地定位项目中隐藏的.git文件夹,然后将其删除。这将删除本地存储库。接下来,更新vue.config.js文件,就像这样:

module.exports = {
    publicPath: process.env.NODE_ENV === 'production'
      ? '/chp8/'
      : '/'
  }

回到 GitHub Desktop,应用程序将注意到您的更改并提供您发布存储库的选项。提供的存储库名称是chapter8,但您需要将其重命名为chp8。回到 GitHub,在您的新chp8存储库中,将其设置为公共。请注意,您可以在 GitHub Desktop 的弹出窗口中完成此操作。无论您如何做到这一点,使存储库公开是很重要的。接下来,在 GitHub 存储库仪表板的设置选项卡中向下滚动到 GitHub Pages 部分,并在主分支上发布一个新的 GitHub Pages 项目,就像我们之前所做的那样。

目前,在 Vue 文档中并不十分清楚如何轻松地在 GitHub Pages 上部署网站。目前有效的方法是将您的dist文件夹发布为子树存储库。以下是用于实现此目的的命令:

git init  # with /dist un-ignored in .gitignore
npm run build
git add dist
git commit -m "Init dist"
git status
git subtree push --prefix dist origin master
git add --all
git commit -m "Publish all"
 create mode 100644 README.md
 create mode 100644 babel.config.js
 create mode 100644 package-lock.json
 create mode 100644 package.json
 create mode 100644 public/favicon.ico
 create mode 100644 public/index.html
 create mode 100644 src/App.vue
 create mode 100644 src/assets/logo.png
 create mode 100644 src/components/HelloWorld.vue
 create mode 100644 src/main.js
# make some additional changes, follow it up with ''npm run build''
git add dist
git commit -m "Publish chp8 title"
git subtree push --prefex origin master

本章的存储库可以在https://github.com/ImsirovicAjdin/chp8找到。如果您查看文件结构,您会注意到您的存储库看起来像这样:

css/
  └── app.11c93175.css
img/
 └── logo.82b9c7a5.png
js/
 ├── app.8c7f6fb3.js
 ├── app.8c7f6fb3.map
 ├── chunk-vendors.ecd76ec1.js
 └── chunk-vendors.ecd76ec1.js.map
favicon.ico
index.html

显然,git subtree push --prefix dist origin master命令只推送了dist目录的内容到 GitHub。要更好地理解本章的存储库是如何工作的,请参考本书代码中的chapter8文件夹,并在打开后,在命令行程序中运行git log命令。

总结

在本章中,我们学习了 Git 和 GitHub 的基础知识。我们已经了解了如何设置和使用 GitHub Desktop,以及如何使用它快速轻松地将本地存储库推送到 GitHub 上的远程存储库。

此外,我们已经学习了如何向我们的应用程序添加分支,以及如何拉取这些分支并将它们与主分支合并。最后,我们讨论了我们需要对项目进行的调整,以便在 GitHub Pages 上发布它。

标签:指南,vue,CLI3,js,webpack,Vue,我们,CLI
From: https://www.cnblogs.com/apachecn/p/18195742

相关文章

  • 使用-Jest-测试-VueJS-组件-全-
    使用Jest测试VueJS组件(全)原文:zh.annas-archive.org/md5/fe8124600bcfb5515d84e359068f7e7c译者:飞龙协议:CCBY-NC-SA4.0前言关于本节简要介绍了作者以及本书涵盖的内容。关于本书在现代基于组件的JavaScript框架中进行单元测试并不简单。您需要一个可靠且运行迅速......
  • Vue3开发新范式,不用`ref/reactive`,不用`ref.value`
    什么是Cabloy-Front?Cabloy-Front是一款支持IOC容器的Vue3框架。不用ref/reactive,不用ref.value,不用pinia与UI库的配合Cabloy-Front可以搭配任何UI库使用,并且内置了几款UI库的项目模版,便于开箱即用,包括:antdvelement-plusquasarvuetify特性Cabloy-Front为Vue......
  • vue3 elementplus样式
    科技感日期选择器样式.data_screen.el-picker-panel__footer{color:#87CEEB;background:#00122a;border-top:1pxsolid#274954;}.data_screen.el-picker-panel{color:#87CEEB;background:#00122a;border:1pxsolid#274954;}.data_screen.el-picker-pane......
  • Vue使用AES加密
    1.安装crypto-js库:npminstallcrypto-js#或yarnaddcrypto-js2.封装encryption.js//utils/encryption.jsimportCryptoJSfrom'crypto-js';//AES加密exportfunctionencrypt(text,key){returnCryptoJS.AES.encrypt(text,key).toString();}//......
  • elementUI中Vue 2方式<el-table>表格中列表列头内容过长,不换行处理
    使用render-header属性<el-table-column...:render-header="headerRender"></el-table-column>methods:{headerRenderer(h,{column}){//使用h函数创建VNode,防止表头内容换行returnh('div',{style:{......
  • vue 常见面试题
    1.VueJS的特点是什么?VueJS的特点有以下几个:1.简洁易用:VueJS的核心库只关注视图层,提供了简洁明了的API,便于开发者快速上手和编写代码。2.双向数据绑定:VueJS采用了基于数据劫持的双向数据绑定机制,能够自动追踪数据的变化,并通过更新视图实现数据的自动同步。3.组件化:VueJS支......
  • vue2 使用echarts实现地图点击进入下一层级+点击空白处回退
    先验知识:vue2中echarts的安装和显示中国地图:https://www.cnblogs.com/sunshine233/p/16140522.html鼠标事件: https://echarts.apache.org/zh/api.html#echartsInstance.onecharts.getMap():https://echarts.apache.org/zh/api.html#echarts.getMap监听“空白处”的事件:https:/......
  • vue 面试题
    以下是一些常见的Vue面试题:1.Vue.js是什么?有什么特点?Vue.js是一个用于构建用户界面的渐进式JavaScript框架。它采用了MVVM(模型-视图-视图模型)的架构模式,可以使开发者更容易地构建高效、可维护的Web应用程序。Vue.js具有以下特点:1.简洁:Vue.js的核心库只关注视图层,减少了学习......
  • vue 前端配置
    前端配置1axios安装cnpminstallaxios-Smain.js中importaxiosfrom'axios'Vue.prototype.$axios=axios2elementui安装cnpminstallelement-ui-Smain.js中importElementUIfrom'element-ui';import'element-ui/lib/theme-cha......
  • vue3 pinia
    pinia状态管理器,统一状态管理,组件间通信state、getter和action,我们可以假设这些概念相当于组件中的data、computed和methods1安装npminstallpinia2在store/xx.js,写入代码,可以定义多个import{defineStore}from"pinia";exportconstuseCountStore=defineS......