Vue CLI3 快速启动指南(二)
原文:
zh.annas-archive.org/md5/31ebad88f7990ce0d7b13055dbe49dcf译者:飞龙
第五章: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。
-
从 Windows 资源管理器中打开
vueclichapter5文件夹,在vueclichapter5文件夹内的空白处右键单击,然后单击“Git Bash here”命令。 -
一旦 Git Bash 打开,输入
code .并按Enter键。这将打开一个全新的 VS Code 实例,除了欢迎标签之外,没有其他文件或选项卡。 -
接下来,我们将直接从 VS Code 的集成终端中添加一个新的 Vue 项目。要访问这个终端,点击 VS Code 窗口(使其获得焦点),然后按以下快捷键:Ctrl + `。
我们之前已经提到了Ctrl反引号快捷键。作为提醒,`字符可以在键盘上按下Tab键上方的键时找到。
使用Ctrl + *`*键盘快捷键将在 VS Code 中打开终端。
- 接下来,我们将运行
vue create命令,后面跟着一个点,如下所示:
vue create .
这样做将在现有文件夹中生成一个 Vue 项目,也就是说,它不会为我们的新 Vue 项目创建一个子文件夹,如下所示:
图 5.1:从 VS Code 的终端在当前目录中生成项目
- 按下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-router和Add 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 应用,只需点击输出日志中列出的Local或NetworkURL 之一即可。
在 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.vue和About.vue。在我们项目的根目录中,我们还可以看到一些额外的文件:router.js、store.js、.browserslistrc、eslintrc.js、postcss.config.js和README.md。
router.js文件是 vue-router 用来设置应用程序中路径的文件。routes数组是一组对象:一个对象对应一个路由。由于默认安装中有两个路由,所以routes数组中有两个对象。store.js文件是 vuex 用来跟踪我们应用程序的状态、mutations 和 actions 的文件;这些都被称为vuex store。README.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.vue和About.vue文件,我们还可以看到router-view标签(在具有id为nav的div下方)。这实际上是渲染Home view或About view的地方。将要渲染的组件将由与to属性映射的内容确定。
渲染 Vue 实例并将其挂载到#app
最后,调用一个 Vue 的新实例,并传递一个选项对象作为参数。该对象接收以下键值对:router: router、store: store和render: 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 中的 Webpack,dist文件夹是 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.vue的methods选项中导航到路由,可以在组件的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.
使用本地安装的包的一个缺点是,特定命令,如prettier、webpack或eslint,不会在命令行上可用。相反,您需要将本地安装的节点模块作为 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'
]
}
};
在配置文件中导出的对象内部,我们可以看到环境设置为 browser,es6 属性设置为 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-style和indent规则的错误级别将是error,而quotes和semi规则的错误级别将是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 一起工作。方法如下:
- 我们首先要将 Vue UI 指向根文件夹,如下所示。重要的是要验证您不在现有的 Vue 应用程序内:
图 6.3:在 Vue CLI 3 UI 中创建新项目
- 接下来,我们将点击“选择此文件夹”按钮继续,然后按照以下方式选择我们项目的名称:
图 6.4:添加项目名称
-
接下来,我们将点击“选择此文件夹”按钮继续,然后选择我们项目的名称。点击“下一步”继续,您将被带到预设选项卡。
-
一旦您在预设选项卡上,选择手动预设以手动选择功能,然后再次点击“下一步”。在功能选项卡上,Babel 和代码检查/格式化功能应该已经被预先选择,所以只需再次点击“下一步”进入配置屏幕,如下所示:
图 6.5:从配置屏幕中选择 ESLint + Prettier
- “选择一个代码检查/格式化配置”给了我们几个选项。在底部选择ESLint + Prettier。一旦我们点击它,就会出现一个选项来保存预设,所以让我们按照以下图片保存它:
图 6.6:在 Vue CLI 3 UI 中保存新预设
-
一旦我们点击“创建新预设”按钮,我们就完成了对项目的自定义,然后我们可以等待所有依赖项安装完成。
-
完成后,您将看到“欢迎使用新项目”的消息。现在,您可以点击左侧菜单上的“项目依赖”链接。除了预期的依赖项(
babel-eslint,eslint,eslint-plugin-vue和vue-template-compiler)之外,您还会看到@vue/eslint-config-prettier开发依赖项。正如我们所看到的,这是一个官方的vue npm模块,因为它有@vue命名空间。
总结
在本章中,我们已经看到了npm和npx、全局和本地安装节点模块之间的区别。我们进一步讨论了 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 属性中。接受的值为primary、secondary、success、danger、info、warning、light和dark。
在前面的例子中,我们使用了值为secondary的variant,这给了我们一个灰色的背景,鼠标悬停时显示白色的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 <user@email.com>
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 工作流程:
-
我们使用
vue create <appname>来安装一个应用程序。 -
作为安装的一部分,我们的应用程序被初始化为一个 Git 存储库。
-
安装完成后,我们拥有了所有的文件(工作目录)和一个单独的提交(带有消息“init”,表示已初始化存储库)。
-
然后,我们对工作目录进行了一些更改。
-
在提交这些更改之前,我们需要将它们添加到我们的暂存索引中。暂存索引只是一棵准备提交的更新文件的树。如果我们没有使用
git add <filename>命令添加任何文件,我们的暂存索引就是空的。 -
当您将所有文件暂存到暂存区后,然后提交它们(使用
git commit -m语法,后面跟着引号内的特定提交消息)。 -
当您提交了更改后,您只需重复这个过程。
除了工作目录和暂存区,第三棵树就是存储库。您可以使用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 上发布它。