1. 創建項目骨架
# 1. 利用Vue-CLI創建項目 vue create vue-login #2. 添加依賴框架 # 進入到項目根目錄 cd vue-login # 添加 element,一個 element 風格的 UI 框架 vue add element # 安裝 axios,用於網絡請求 npm install axios # 安裝 Vuex,用於管理狀態 npm install vuex --save # 安裝 路由,用於實現兩個 Vue 頁面的跳轉 npm install vue-router
2. 創建相應功能的目錄結構,進行分層開發
- api (網絡請求接口包) - router (路由配置包) - store (Vuex 狀態管理包) - utils (工具包) - views (vue 視圖包,存放所有 vue 代碼,可根據功能模塊進行相應分包)
3. 運行項目
npm run serve 在瀏覽器輸入:http://localhost:8080/
4. View 層代碼編寫
編寫三個 vue 文件:
login.vue(登錄頁面)
success.vue(登錄成功頁面)
error.vue(登錄失敗頁面)
login.vue
<template> <div> <el-card class="login-form-layout"> <el-form autocomplete="on" :model="loginForm" ref="loginForm" label-position="left" > <div style="text-align: center"> <svg-icon icon-class="login-mall" style="width: 56px;height: 56px;color: #409EFF"></svg-icon> </div> <h2 class="login-title color-main">登錄頁面</h2> <el-form-item prop="username"> <el-input name="username" type="text" v-model="loginForm.username" autocomplete="on" placeholder="請輸入用戶名" > <span slot="prefix"> <svg-icon icon-class="user" class="color-main"></svg-icon> </span> </el-input> </el-form-item> <el-form-item prop="password"> <el-input name="password" :type="pwdType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autocomplete="on" placeholder="請輸入密碼" > <span slot="prefix"> <svg-icon icon-class="password" class="color-main"></svg-icon> </span> <span slot="suffix" @click="showPwd"> <svg-icon icon-class="eye" class="color-main"></svg-icon> </span> </el-input> </el-form-item> <el-form-item style="margin-bottom: 60px"> <el-button style="width: 100%" type="primary" :loading="loading" @click.native.prevent="handleLogin" >登錄</el-button> </el-form-item> </el-form> </el-card> </div> </template> <script> export default { name: "login", data() { return { loginForm: { username: "admin", password: "123456" }, loading: false, pwdType: "password", }; }, methods: { showPwd() { if (this.pwdType === "password") { this.pwdType = ""; } else { this.pwdType = "password"; } }, handleLogin() { this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true; this.$store .dispatch("Login", this.loginForm) .then(response => { this.loading = false; let code = response.data.code; if (code == 200) { this.$router.push({ path: "/success", query: { data: response.data.data } }); } else { this.$router.push({ path: "/error", query: { message: response.data.message } }); } }) .catch(() => { this.loading = false; }); } else { // eslint-disable-next-line no-console console.log("參數驗證不合法!"); return false; } }); } } }; </script> <style scoped> .login-form-layout { position: absolute; left: 0; right: 0; width: 360px; margin: 140px auto; border-top: 10px solid #409eff; } .login-title { text-align: center; } .login-center-layout { background: #409eff; width: auto; height: auto; max-width: 100%; max-height: 100%; margin-top: 200px; } </style>
success.vue
<template> <div> <h1>Welcome!{{msg}}</h1> </div> </template> <script> export default { data() { return { msg: this.$route.query.data }; }, // data() { //這種方式也可以 // return { // msg: null // }; // }, // created() { // this.msg = this.$route.query.data; // } } </script>
error.vue
<template> <div> <h1>登錄錯誤:{{msg}}</h1> </div> </template> <script> export default { // data() { // return { // msg: this.$route.query.data // }; // }, //使用這種方式也可以顯示 msg data() { return { msg: null }; }, created() { this.msg = this.$route.query.message; } };
5. 路由
頁面寫好了,我們需要依次顯示這三個頁面,這里我們統一使用路由來管理顯示頁面。
5-1) 創建路由配置文件
在router 文件夾下創建一個 index.js 文件,內容如下:
import Vue from 'vue' //引入 Vue import VueRouter from 'vue-router' //引入 Vue 路由 Vue.use(VueRouter); //安裝插件 export const constantRouterMap = [ //配置默認的路徑,默認顯示登錄頁 { path: '/', component: () => import('@/views/login')}, //配置登錄成功頁面,使用時需要使用 path 路徑來實現跳轉 { path: '/success', component: () => import('@/views/success')}, //配置登錄失敗頁面,使用時需要使用 path 路徑來實現跳轉 { path: '/error', component: () => import('@/views/error'), hidden: true } ] export default new VueRouter({ // mode: 'history', //后端支持可開 scrollBehavior: () => ({ y: 0 }), routes: constantRouterMap //指定路由列表
5-2) 將路由添加到程序入口
路由配置文件寫好,我們需要把他引入到 main.js 中。
在項目的 src 目錄根節點下,找到 main.js。
import Vue from 'vue' import App from './App.vue' import './plugins/element.js' import router from './router' //引入路由配置 Vue.config.productionTip = false new Vue({ render: h => h(App), router, //使用路由配置 }).$mount('#app')
5-3) 配置路由的出入口
現在路由已經完全引入到項目了,但是路由還需要一個出入口,
這個出入口用來告訴路由將路由的內容顯示在這里。
修改 App.vue 內容如下:
<template> <div id="app"> <!-- 路由的出入口,路由的內容將被顯示在這里 --> <router-view/> </div> </template> <script> export default { name: 'App' } </script>
現在運行程序, 界面如下:
5-4) 路由跳轉
this.$router.push({path: "路徑"})
在 login.vue 中可以使用 this.$router.push({path: "路徑"}) 來跳轉到指定路徑的路由組件中, 路由跳轉核心代碼如下: this.$router.push({path: "/success"}); //跳轉到成功頁 this.$router.push({path: "/error"}); //跳轉到失敗頁
完整代碼如下
login.vue
handleLogin() { this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true; this.$store .dispatch("Login", this.loginForm) .then(response => { this.loading = false; let code = response.data.code; if (code == 200) { this.$router.push({ path: "/success", query: { data: response.data.data } }); } else { this.$router.push({ path: "/error", query: { message: response.data.message } }); } }) .catch(() => { this.loading = false; }); } else { // eslint-disable-next-line no-console console.log("參數驗證不合法!"); return false; } }); }
6. 使用 Vuex + Axios 方式進行網絡請求
6-1) 利用Axios封裝請求
axios 是一個網絡請求構架,官方推薦使用這種方式進行 http 的請求。
a) 在 utils 包下封裝一個請求工具類 request.js
import axios from 'axios' //引入 axios import baseUrl from '../api/baseUrl' //使用環境變量 + 模式的方式定義基礎URL // 創建 axios 實例 const service = axios.create({ baseURL: baseUrl, // api 的 base_url timeout: 15000, // 請求超時時間 }) export default service
注: 這里的 baseUrl 涉及 Vue CLI3 的環境變量與模式的概念,見:Vue 環境變量和模式(設置通用baseUrl)
b) 登錄請求接口 API
在 api 文件夾下,創建一個登錄API文件
login.js
import request from '@/utils/request' //引入封裝好的 axios 請求 export function login(username, password) { //登錄接口 return request({ //使用封裝好的 axios 進行網絡請求 url: '/admin/login', method: 'post', data: { //提交的數據 username, password } }) }
6-2) 使用 Vuex 封裝 axios
Vuex 是一個狀態管理構架。
a)封裝 Vuex 中的 module
在 store 文件夾下創建一個 modules 文件夾,然后在此文件夾下創建一個 user.js 文件
import { login } from '@/api/login'//引入登錄 api 接口 const user = { actions: { // 登錄 Login({ commit }, userInfo) { //定義 Login 方法,在組件中使用 this.$store.dispatch("Login") 調用 const username = userInfo.username.trim() return new Promise((resolve, reject) => { //封裝一個 Promise login(username, userInfo.password).then(response => { //使用 login 接口進行網絡請求 commit('') //提交一個 mutation,通知狀態改變 resolve(response) //將結果封裝進 Promise }).catch(error => { reject(error) }) }) }, } } export default user
上面的代碼值得解釋一下:
1. 引接口 引入 login 接口,之后使用登錄接口進行網絡請求。 2. 定義action 定義一個 名為 Login 的 action 方法,方便Vue 組件通過 this.$store.dispatch("Login") 調用。 3. 封裝Promise Promise,這個類很有意思,官方的解釋是“store.dispatch 可以處理被觸發的 action 的處理函數返回的 Promise, 並且 store.dispatch 仍舊返回 Promise”。 這話的意思組件中的 dispatch 返回的仍是一個 Promise 類。 因此Promise 中的兩個方法 resolve() 與 reject() 分別對應 dispatch 中的 then 與 catch。
b) 創建 Vuex
在 store 文件夾下創建一個 index.js 文件
import Vue from 'vue' //引入 Vue import Vuex from 'vuex' //引入 Vuex import user from './modules/user' //引入 user module Vue.use(Vuex) const store = new Vuex.Store({ modules: { user //使用 user.js 中的 action } }) export default store
c) 將 Vuex 添加到 main.js 文件
修改之前的 main.js 文件如下:
import Vue from 'vue' import App from './App.vue' import './plugins/element.js' import router from './router' //引入路由配置 import store from './store' //引入 Vuex 狀態管理 Vue.config.productionTip = false new Vue({ render: h => h(App), router, //使用路由配置 store //使用 Vuex 進行狀態管理 }).$mount('#app')
7. 服務端接口
由於這是一篇主要講Vue的文章, 所以服務端接口這里我就一筆帶過了。
可以寫一個簡易的不帶數據庫的登錄接口(Java)如下:
@RestController public class LoginController { @RequestMapping(value = "/admin/login", method = RequestMethod.POST) public CommonResult login(@RequestBody User user) { if (user.getUsername().equals("admin") && user.getPassword().equals("123456")) return CommonResult.success("admin"); else return CommonResult.validateFailed(); } }
再次訪問頁面, 效果如下:
登錄成功
登錄失敗