Vue CLI 简介
在第五章 “添加 Vue 组件” 中,我们使用 webpack
创建了自定义的 Vue SFC
应用。作为一名开发者,了解复杂事物的内部机制很有用,我们也必须理解如何使用通用和标准的模式与他人协作。因此,现在我们倾向于使用框架。Vue CLI
是 Vue
应用开发的标准工具。它完成了我们的 webpack
自定义工具所做的工作,甚至更多。如果你不想创建自己的 Vue SFC
开发工具,Vue CLI
是一个绝佳的选择。它开箱即用地支持 Babel
、ESLint
、TypeScript
、PostCSS
、PWA
、单元测试和端到端测试。要了解更多关于 Vue CLI
的信息,请访问 https://cli.vuejs.org/zh/。
安装 Vue CLI
使用 Vue CLI
非常容易上手。请执行以下步骤:
-
使用
npm
全局安装它:$ npm i -g @vue/cli
-
在你想要创建项目时执行:
$ vue create my-project
-
你将被提示选择一个预设 - 默认或手动选择功能,如下所示:
Vue CLI v4.4.6 ? Please pick a preset: (Use arrow keys) > default (babel, eslint) Manually select features
-
选择默认预设,因为我们稍后可以手动安装我们需要的东西。安装完成后,你应该在终端中看到类似于以下输出最后一部分的内容:
Successfully created project my-project. Get started with the following commands: $ cd my-project $ npm run serve
-
将你的目录更改为
my-project
并开始开发过程:$ npm run serve
你应该会看到类似这样的内容:
DONE Compiled successfully in 3469ms App running at: - Local: http://localhost:8080/ - Network: http://199.188.0.44:8080/ Note that the development build is not optimized. To create a production build, run npm run build.
在接下来的章节中,我们将使用 Vue CLI
将你在前面章节中学到的导航守卫转换为适当的中间件。这意味着我们将把所有的钩子和守卫分离到单独的 .js
文件中,并将它们保存在一个名为 middlewares
的公共文件夹中。但是,在此之前,我们应该首先了解 Vue CLI
为我们生成的项目目录结构,然后添加我们自己需要的目录。让我们开始吧。
理解 Vue CLI 的项目结构
使用 Vue CLI
创建项目后,如果你查看项目目录内部,你会看到它为我们提供了一个基本的结构,如下所示:
├── package.json
├── babel.config.js
├── README.md
├── public
│ ├── index.html
│ └── favicon.ico
└── src
├── App.vue
├── main.js
├── router.js
├── components
│ └── HelloWorld.vue
└── assets
└── logo.png
从这个基本结构,我们可以构建和扩展我们的应用。因此,让我们在 /src/
目录下开发我们的应用,并使用一个路由文件向其添加以下目录:
└── src
├── middlewares/
├── store/
├── routes/
└── router.js
我们将创建两个路由组件,login
和 secured
,作为 SFC
页面,并将 secured
页面设置为 403
保护页面,这将要求用户登录以提供他们的姓名和年龄才能访问该页面。以下是我们这个简单的 Vue
应用在 /src/
目录下需要的文件和结构:
└── src
├── App.vue
├── main.js
├── router.js
├── components
│ ├── secured.vue
│ └── login.vue
├── assets
│ └── ...
├── middlewares
│ ├── isLoggedIn.js
│ └── isAdult.js
├── store
│ ├── index.js
│ ├── mutations.js
│ └── actions.js
└── routes
├── index.js
├── secured.js
└── login.js
我们现在对我们的应用需要哪些目录和文件有了一个概念。接下来,我们将继续编写这些文件的代码。
使用 Vue CLI 编写中间件和 Vuex store
查看 package.json
,你会发现 Vue CLI
附带的默认依赖项非常基础和精简:
// package.json
"dependencies": {
"core-js": "^2.6.5",
"vue": "^2.6.10"
}
因此,我们将安装我们的项目依赖项并在以下步骤中编写所需的代码:
-
通过
npm
安装以下包:$ npm i vuex $ npm i vue-router $ npm i vue-router-multiguard
请注意,
Vue
不支持每个路由多个守卫。因此,如果你想为一个路由创建多个守卫,Vue Router Multiguard 允许你这样做。有关此软件包的更多信息,请访问 https://github.com/atanas-dev/vue-router-multiguard。 -
创建
state
、actions
和mutations
,将认证的用户详细信息存储在Vuex store
中,以便任何组件都可以访问这些详细信息:// src/store/index.js import Vue from 'vue' import Vuex from 'vuex' import actions from './actions' import mutations from './mutations' Vue.use(Vuex) export default new Vuex.Store({ state: { user: null }, actions, mutations })
为了提高可读性和简洁性,我们将
store
的actions
分离到单独的文件中,如下所示:// src/store/actions.js const actions = { async login({ commit }, { name, age }) { if (!name || !age) { throw new Error('错误的凭据') } const data = { name: name, age: age } commit('setUser', data) }, async logout({ commit }) { commit('setUser', null) } } export default actions
我们还将
store
的mutations
分离到单独的文件中,如下所示:// src/store/mutations.js const mutations = { setUser (state, user) { state.user = user } } export default mutations
-
创建一个中间件以确保用户已登录:
// src/middlewares/isLoggedIn.js import store from '../store' export default (to, from, next) => { if (!store.state.user) { const err = new Error('你尚未连接') err.statusCode = 403 next(err) } else { next() } }
-
创建另一个中间件以确保用户年满 18 岁:
// src/middlewares/isAdult.js import store from '../store' export default (to, from, next) => { if (store.state.user.age < 18) { const err = new Error('你必须年满 18 岁') err.statusCode = 403 next(err) } else { next() } }
-
通过使用
vue-router-multiguard
在beforeEnter
中插入多个中间件,将这两个中间件导入到受保护的路由中:// src/routes/secured.js import multiguard from 'vue-router-multiguard' import secured from '../components/secured.vue' import isLoggedIn from '../middlewares/isLoggedIn' import isAdult from '../middlewares/isAdult' export default { name: 'secured', path: '/secured', component: secured, beforeEnter: multiguard([isLoggedIn, isAdult]) }
-
使用一个简单的登录页面创建客户端身份验证。以下是我们登录(
login
)和注销(logout
)方法所需的基本输入字段:// src/components/login.vue <template> <form @submit.prevent="login"> <p>姓名: <input v-model="name" type="text" name="name"></p> <p>年龄: <input v-model="age" type="number" name="age"></p> <button type="submit">提交</button> </form> </template> <script> export default { data() { return { error: null, name: '', age: '' } }, methods: { async login() { try { await this.$store.dispatch('login', { name: this.name, age: this.age }); this.$router.push({ name: 'secured' }); } catch (error) { this.error = error.message; } }, async logout() { await this.$store.dispatch('logout'); this.$router.push({ name: 'login' }); } } } </script>
-
完成前面的登录和登出方法,通过在
try
和catch
代码块中分发login
和logout
action 方法,如下所示:async login() { try { await this.$store.dispatch('login', { name: this.name, age: this.age }); this.name = ''; this.age = ''; this.error = null; } catch (e) { this.error = e.message; } }, async logout() { try { await this.$store.dispatch('logout'); } catch (e) { this.error = e.message; } }
-
创建登录路由:
// src/routes/login.js import login from '../components/login.vue' export default { name: 'login', path: '/', component: login }
请注意,我们将此路由命名为
login
,因为稍后当我们在前面的中间件中收到身份验证错误时,我们需要使用此名称来重定向导航路由。 -
将登录(
login
)和受保护(secured
)的路由导入到索引路由中,如下所示:// src/routes/index.js import login from './login' import secured from './secured' const routes = [ login, secured ] export default routes
-
将前面的索引路由导入到
Vue Router
实例中,并使用router.onError
捕获路由错误,如下所示:// src/router.js import Vue from 'vue' import VueRouter from 'vue-router' import Routes from './routes' Vue.use(VueRouter) const router = new VueRouter({ routes: Routes }) router.onError(err => { alert(err.message) router.push({ name: 'login' }) }) export default router
在这一步中,我们使用
router.onError
来处理从中间件传递的Error
对象,并使用router.push
在未满足身份验证条件时将导航路由重定向到登录页面。对象的name
必须与步骤 7 中的登录路由的name
相同,即login
。 -
将
router
和store
导入到main
文件中:// src/main.js import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' new Vue({ router, store, render: h => h(App), }).$mount('#app')
-
使用
npm run serve
运行项目,你应该看到应用加载在localhost:8080
上。如果你在主页的输入字段中输入一个姓名和一个小于 18 的数字,然后点击登录按钮,当你尝试访问受保护的页面时,你应该会收到一个提示框,显示 “你必须年满 18 岁”。另一方面,如果你输入一个大于 18 的数字,你应该在受保护的页面上看到姓名和数字:姓名: John 年龄: 20
你可以在我们的
GitHub
仓库的/chapter-11/vue/vuecli/basic/
中找到此应用的完整代码。你也可以在/chapter-11/vue/webpack/
中找到使用自定义webpack
的应用。
做得好!你已经成功完成了 Vue
项目中间件的所有章节。现在,让我们在接下来的章节中应用你刚刚学到的关于 Nuxt
项目的知识。