---恢復內容開始---前端
內容:
一、mock.js模擬響應ajax請求
二、經過js代碼完成路由的跳轉
三、後臺主界面的搭建
四、退出功能
五、左側樹收縮功能(vue總線的概念)vue
1. Mock.js
先後端分離開發開發過程中,常常會遇到如下幾個尷尬的場景:
1. 老大,接口文檔還沒輸出,個人好多活幹不下去啊!
2. 後端小哥,接口寫好了沒,我要測試啊!
先後端分離以後,前端迫切須要一種機制,再也不須要依賴後端接口開發,而今天的主角mockjs就能夠作到這一點node
Mock.js是一個模擬數據的生成器,用來幫助前端調試開發、進行先後端的原型分離以及用來提升自動化測試效率。ios
衆所周知Mock.js由於兩個重要的特性風靡前端:
數據類型豐富
支持生成隨機的文本、數字、布爾值、日期、郵箱、連接、圖片、顏色等。
攔截Ajax請求
不須要修改既有代碼,就能夠攔截Ajax請求,返回模擬的響應數據。
更多內容,能夠雲Mockjs官方查看「http://mockjs.com/」ajax
注1:easy-mock,一個在線模擬後臺的數據平臺正則表達式
2. Mock.js使用步驟
2.1 安裝mockjs依賴
npm install mockjs -D #只在開發環境使用npm
2.2 引入
爲了只在開發環境使用mock,而打包到生產環境時自動不使用mock,咱們能夠在env中作一個配置
(1)dev.env
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
MOCK: 'true'
})json
(2)prod.env
module.exports = {
NODE_ENV: '"production"',
MOCK: 'false'
}axios
(3)main.js
//開發環境下才會引入mockjs
process.env.MOCK && require('@/mock')後端
注1:import是ES6標準中的模塊化解決方案,require是node中遵循CommonJS規範的模塊化解決方案
後者支持動態引入,也就是require(${path}/xx.js)
2.3 目錄和文件建立
在src目錄下建立mock目錄,定義mock主文件index.js,並在該文件中定義攔截路由配置,
/src/mock/index.js
import Mock from 'mockjs' //引入mockjs,npm已安裝
import action from '@/api/action' //引入請求地址
//全局設置:設置全部ajax請求的超時時間,模擬網絡傳輸耗時
Mock.setup({
// timeout: 400 //延時400s請求到數據
timeout: 200 - 400 //延時200-400s請求到數據
})
//引登錄的測試數據,並添加至mockjs
import loginInfo from '@/mock/json/login-mock.js'
let s1 = action.getFullPath('SYSTEM_USER_DOLOGIN')
Mock.mock(s1, "post", loginInfo)
// Mock.mock(s1, /post|get/i, loginInfo)
導入公共模塊及mockjs全局設置
import Mock from 'mockjs' //引入mockjs,npm已安裝
import action from '@/api/action' //引入封裝的請求地址
//全局設置:設置全部ajax請求的超時時間,模擬網絡傳輸耗時
Mock.setup({
// timeout: 400 //延時400s請求到數據
timeout: 200 - 400 //延時200-400s請求到數據
})
注1:index.js文件的做用很顯然,就是將分散的xxx-mock文件集合起來.後面再添加新的mock文件,都須要在這裏引入
2.4 爲每一個*.vue定義單獨的xxx-mock.js文件
/src/mock/json/login-mock.js
注1:能夠添加自定義的json數據
注2:還能夠經過mockjs的模板生成隨機數據
2.5 在index.js中導入xxx-mock.js,並添加攔截路由配置
import loginInfo from '@/mock/json/login-mock.js'
Mock.mock(url, "post", {...})
注1:如何同時攔截get/post請求,並對get和post請求大小寫不敏感呢?那就請使用正則表達式吧
Mock.mock(url, /post|get/i,{})
注2:Mockjs如何攔截帶參數的GET請求
在實踐過程當中,發現mockjs對GET請求的支持並非很友好。
例如:使用 Mock.mock("/user/getUserInfo", "get", mockData) 的時候,它只會攔截url等於 /user/getUserInfo 的請求,
而對於帶參數的請求,如/user/getUserInfo?id=12,由於不等於 /user/getUserInfo 就攔截不到。
解決方案:經過正則表達式實現
Mock.mock(RegExp(url + ".*"), /post|get/i, {...});
注3:定義攔截路由配置最簡單的方式就是使用POST請求,而且不在URL中添加參數(推薦)
注4:還能夠經過控制檯將將請求和參數都打印出來,以便調試
Mock.mock(url, "get", (options) =>{
// 最佳實踐,
console.debug(url, options);
return Mock.mock(mockUserInfo);
});
2.6 以後ajax請求便會被mock攔截了
## 登錄與註冊頁面的跳轉
3. 使用this.$router.push({})實現路由跳轉
3.1 字符串
this.$router.push('/home/first')
3.2 對象
this.$router.push({ path: '/home/first' })
3.3 命名的路由
this.$router.push({ name: 'home', params: { userId: wise }})
3.4 this.$router.push、replace、go的區別
this.$router.push()
跳轉到不一樣的url,但這個方法會向history棧添加一個記錄,點擊後退會返回到上一個頁面
this.$router.replace()
一樣是跳轉到指定的url,可是這個方法不會向history裏面添加新的記錄,點擊返回,會跳轉到上上一個頁面。上一個記錄是不存在的。
this.$router.go(n)
相對於當前頁面向前或向後跳轉多少個頁面,相似 window.history.go(n)。n可爲正數可爲負數。負數返回上一個頁面
<template> <div class="login-wrap"> <el-form :model="ruleForm" label-width="100px" class="demo-ruleForm login-container"> <h3 style="text-align: center;">用戶登陸</h3> <el-form-item label="用戶名" prop="uname"> <el-input type="uname" v-model="ruleForm.uname" autocomplete="off"></el-input> </el-form-item> <el-form-item label="密碼" prop="pwd"> <el-input type="pwd" v-model="ruleForm.pwd" autocomplete="off"></el-input> </el-form-item> <el-form-item> <el-row> <el-col :span="24"> <div class="grid-content bg-purple-dark"> <el-button style="width: 100%;" type="primary" @click="doSub">提交</el-button> </div> </el-col> </el-row> <el-row> <el-col :span="12"> <div class="grid-content bg-purple-dark"> <el-link type="success" @click="toReg">用戶註冊</el-link> </div> </el-col> <el-col :span="12"> <div class="grid-content bg-purple-dark"> <el-link type="success">忘記密碼</el-link> </div> </el-col> </el-row> </el-form-item> </el-form> </div> </template> <script> export default { data(){ return{ ruleForm:{ uname:'', pwd:'' } }; }, methods:{ doSub(){ let url = this.axios.urls.SYSTEM_USER_DOLOGIN; this.axios.post(url, this.ruleForm).then((response)=>{ console.log(response); if(response.data.code == 1){ this.$message({ showClose:true, message: response.data.msg, type: 'success' }); this.$router.push({ path:'/AppMain' }) }else{ this.$message({ showClose: true, message: response.data.msg, type: 'error' }); } }).catch(function(error) { console.log(error); }); }, toReg(){ this.$router.push({ path:'/Reg' }); } } } </script> <style scoped> .login-wrap { box-sizing: border-box; width: 100%; height: 100%; padding-top: 10%; background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjEzNjFweCIgaGVpZ2h0PSI2MDlweCIgdmlld0JveD0iMCAwIDEzNjEgNjA5IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPCEtLSBHZW5lcmF0b3I6IFNrZXRjaCA0Ni4yICg0NDQ5NikgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+R3JvdXAgMjE8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iQW50LURlc2lnbi1Qcm8tMy4wIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0i6LSm5oi35a+G56CB55m75b2VLeagoemqjCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTc5LjAwMDAwMCwgLTgyLjAwMDAwMCkiPgogICAgICAgICAgICA8ZyBpZD0iR3JvdXAtMjEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc3LjAwMDAwMCwgNzMuMDAwMDAwKSI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iR3JvdXAtMTgiIG9wYWNpdHk9IjAuOCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzQuOTAxNDE2LCA1NjkuNjk5MTU4KSByb3RhdGUoLTcuMDAwMDAwKSB0cmFuc2xhdGUoLTc0LjkwMTQxNiwgLTU2OS42OTkxNTgpIHRyYW5zbGF0ZSg0LjkwMTQxNiwgNTI1LjE5OTE1OCkiPgogICAgICAgICAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLTExIiBmaWxsPSIjQ0ZEQUU2IiBvcGFjaXR5PSIwLjI1IiBjeD0iNjMuNTc0ODc5MiIgY3k9IjMyLjQ2ODM2NyIgcng9IjIxLjc4MzA0NzkiIHJ5PSIyMS43NjYwMDgiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0zIiBmaWxsPSIjQ0ZEQUU2IiBvcGFjaXR5PSIwLjU5OTk5OTk2NCIgY3g9IjUuOTg3NDY0NzkiIGN5PSIxMy44NjY4NjAxIiByeD0iNS4yMTczOTEzIiByeT0iNS4yMTMzMDk5NyI+PC9lbGxpcHNlPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0zOC4xMzU0NTE0LDg4LjM1MjAyMTUgQzQzLjg5ODQyMjcsODguMzUyMDIxNSA0OC41NzAyMzQsODMuNjgzODY0NyA0OC41NzAyMzQsNzcuOTI1NDAxNSBDNDguNTcwMjM0LDcyLjE2NjkzODMgNDMuODk4NDIyNyw2Ny40OTg3ODE2IDM4LjEzNTQ1MTQsNjcuNDk4NzgxNiBDMzIuMzcyNDgwMSw2Ny40OTg3ODE2IDI3LjcwMDY2ODgsNzIuMTY2OTM4MyAyNy43MDA2Njg4LDc3LjkyNTQwMTUgQzI3LjcwMDY2ODgsODMuNjgzODY0NyAzMi4zNzI0ODAxLDg4LjM1MjAyMTUgMzguMTM1NDUxNCw4OC4zNTIwMjE1IFoiIGlkPSJPdmFsLTMtQ29weSIgZmlsbD0iI0NGREFFNiIgb3BhY2l0eT0iMC40NSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02NC4yNzc1NTgyLDMzLjE3MDQ5NjMgTDExOS4xODU4MzYsMTYuNTY1NDkxNSIgaWQ9IlBhdGgtMTIiIHN0cm9rZT0iI0NGREFFNiIgc3Ryb2tlLXdpZHRoPSIxLjczOTEzMDQzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNDIuMTQzMTcwOCwyNi41MDAyNjgxIEw3LjcxMTkwMTYyLDE0LjU2NDA3MDIiIGlkPSJQYXRoLTE2IiBzdHJva2U9IiNFMEI0QjciIHN0cm9rZS13aWR0aD0iMC43MDI2Nzg5NjQiIG9wYWNpdHk9IjAuNyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSIxLjQwNTM1Nzg5OTg3MzE1MywyLjEwODAzNjk1MzQ2OTk4MSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02My45MjYyMTg3LDMzLjUyMTU2MSBMNDMuNjcyMTMyNiw2OS4zMjUwOTUxIiBpZD0iUGF0aC0xNSIgc3Ryb2tlPSIjQkFDQUQ5IiBzdHJva2Utd2lkdGg9IjAuNzAyNjc4OTY0IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1kYXNoYXJyYXk9IjEuNDA1MzU3ODk5ODczMTUzLDIuMTA4MDM2OTUzNDY5OTgxIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTE3IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjYuODUwOTIyLCAxMy41NDM2NTQpIHJvdGF0ZSgzMC4wMDAwMDApIHRyYW5zbGF0ZSgtMTI2Ljg1MDkyMiwgLTEzLjU0MzY1NCkgdHJhbnNsYXRlKDExNy4yODU3MDUsIDQuMzgxODg5KSIgZmlsbD0iI0NGREFFNiI+CiAgICAgICAgICAgICAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLTQiIG9wYWNpdHk9IjAuNDUiIGN4PSI5LjEzNDgyNjUzIiBjeT0iOS4xMjc2ODA3NiIgcng9IjkuMTM0ODI2NTMiIHJ5PSI5LjEyNzY4MDc2Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xOC4yNjk2NTMxLDE4LjI1NTM2MTUgQzE4LjI2OTY1MzEsMTMuMjE0MjgyNiAxNC4xNzk4NTE5LDkuMTI3NjgwNzYgOS4xMzQ4MjY1Myw5LjEyNzY4MDc2IEM0LjA4OTgwMTE0LDkuMTI3NjgwNzYgMCwxMy4yMTQyODI2IDAsMTguMjU1MzYxNSBMMTguMjY5NjUzMSwxOC4yNTUzNjE1IFoiIGlkPSJPdmFsLTQiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMTM0ODI3LCAxMy42OTE1MjEpIHNjYWxlKC0xLCAtMSkgdHJhbnNsYXRlKC05LjEzNDgyNywgLTEzLjY5MTUyMSkgIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTE0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyMTYuMjk0NzAwLCAxMjMuNzI1NjAwKSByb3RhdGUoLTUuMDAwMDAwKSB0cmFuc2xhdGUoLTIxNi4yOTQ3MDAsIC0xMjMuNzI1NjAwKSB0cmFuc2xhdGUoMTA2LjI5NDcwMCwgMzUuMjI1NjAwKSI+CiAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtMiIgZmlsbD0iI0NGREFFNiIgb3BhY2l0eT0iMC4yNSIgY3g9IjI5LjExNzY0NzEiIGN5PSIyOS4xNDAyNDM5IiByeD0iMjkuMTE3NjQ3MSIgcnk9IjI5LjE0MDI0MzkiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yIiBmaWxsPSIjQ0ZEQUU2IiBvcGFjaXR5PSIwLjMiIGN4PSIyOS4xMTc2NDcxIiBjeT0iMjkuMTQwMjQzOSIgcng9IjIxLjU2ODYyNzUiIHJ5PSIyMS41ODUzNjU5Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtMi1Db3B5IiBzdHJva2U9IiNDRkRBRTYiIG9wYWNpdHk9IjAuNCIgY3g9IjE3OS4wMTk2MDgiIGN5PSIxMzguMTQ2MzQxIiByeD0iMjMuNzI1NDkwMiIgcnk9IjIzLjc0MzkwMjQiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yIiBmaWxsPSIjQkFDQUQ5IiBvcGFjaXR5PSIwLjUiIGN4PSIyOS4xMTc2NDcxIiBjeT0iMjkuMTQwMjQzOSIgcng9IjEwLjc4NDMxMzciIHJ5PSIxMC43OTI2ODI5Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI5LjExNzY0NzEsMzkuOTMyOTI2OCBMMjkuMTE3NjQ3MSwxOC4zNDc1NjEgQzIzLjE2MTYzNTEsMTguMzQ3NTYxIDE4LjMzMzMzMzMsMjMuMTc5NjA5NyAxOC4zMzMzMzMzLDI5LjE0MDI0MzkgQzE4LjMzMzMzMzMsMzUuMTAwODc4MSAyMy4xNjE2MzUxLDM5LjkzMjkyNjggMjkuMTE3NjQ3MSwzOS45MzI5MjY4IFoiIGlkPSJPdmFsLTIiIGZpbGw9IiNCQUNBRDkiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iR3JvdXAtOSIgb3BhY2l0eT0iMC40NSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTcyLjAwMDAwMCwgMTMxLjAwMDAwMCkiIGZpbGw9IiNFNkExQTYiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0yLUNvcHktMiIgY3g9IjcuMDE5NjA3ODQiIGN5PSI3LjE0NjM0MTQ2IiByeD0iNi40NzA1ODgyNCIgcnk9IjYuNDc1NjA5NzYiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTAuNTQ5MDE5NjA4LDEzLjYyMTk1MTIgQzQuMTIyNjI2ODEsMTMuNjIxOTUxMiA3LjAxOTYwNzg0LDEwLjcyMjcyMiA3LjAxOTYwNzg0LDcuMTQ2MzQxNDYgQzcuMDE5NjA3ODQsMy41Njk5NjA5NSA0LjEyMjYyNjgxLDAuNjcwNzMxNzA3IDAuNTQ5MDE5NjA4LDAuNjcwNzMxNzA3IEwwLjU0OTAxOTYwOCwxMy42MjE5NTEyIFoiIGlkPSJPdmFsLTItQ29weS0yIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzLjc4NDMxNCwgNy4xNDYzNDEpIHNjYWxlKC0xLCAxKSB0cmFuc2xhdGUoLTMuNzg0MzE0LCAtNy4xNDYzNDEpICI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0xMCIgZmlsbD0iI0NGREFFNiIgY3g9IjIxOC4zODIzNTMiIGN5PSIxMzguNjg1OTc2IiByeD0iMS42MTc2NDcwNiIgcnk9IjEuNjE4OTAyNDQiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC0xMC1Db3B5LTIiIGZpbGw9IiNFMEI0QjciIG9wYWNpdHk9IjAuMzUiIGN4PSIxNzkuNTU4ODI0IiBjeT0iMTc1LjM4MTA5OCIgcng9IjEuNjE3NjQ3MDYiIHJ5PSIxLjYxODkwMjQ0Ij48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtMTAtQ29weSIgZmlsbD0iI0UwQjRCNyIgb3BhY2l0eT0iMC4zNSIgY3g9IjE4MC4wOTgwMzkiIGN5PSIxMDIuNTMwNDg4IiByeD0iMi4xNTY4NjI3NSIgcnk9IjIuMTU4NTM2NTkiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMjguOTk4NTM4MSwyOS45NjcxNTk4IEwxNzEuMTUxMDE4LDEzMi44NzYwMjQiIGlkPSJQYXRoLTExIiBzdHJva2U9IiNDRkRBRTYiIG9wYWNpdHk9IjAuOCI+PC9wYXRoPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTEwIiBvcGFjaXR5PSIwLjc5OTk5OTk1MiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTA1NC4xMDA2MzUsIDM2LjY1OTMxNykgcm90YXRlKC0xMS4wMDAwMDApIHRyYW5zbGF0ZSgtMTA1NC4xMDA2MzUsIC0zNi42NTkzMTcpIHRyYW5zbGF0ZSgxMDI2LjYwMDYzNSwgNC42NTkzMTcpIj4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbC03IiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMC45NDExNzY0NzEiIGN4PSI0My44MTM1NTkzIiBjeT0iMzIiIHJ4PSIxMS4xODY0NDA3IiByeT0iMTEuMjk0MTE3NiI+PC9lbGxpcHNlPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJHcm91cC0xMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzQuNTk2Nzc0LCAyMy4xMTExMTEpIiBmaWxsPSIjQkFDQUQ5Ij4KICAgICAgICAgICAgICAgICAgICAgICAgPGVsbGlwc2UgaWQ9Ik92YWwtNyIgb3BhY2l0eT0iMC40NSIgY3g9IjkuMTg1MzQ3MTgiIGN5PSI4Ljg4ODg4ODg5IiByeD0iOC40NzQ1NzYyNyIgcnk9IjguNTU2MTQ5NzMiPjwvZWxsaXBzZT4KICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkuMTg1MzQ3MTgsMTcuNDQ1MDM4NiBDMTMuODY1NzI2NCwxNy40NDUwMzg2IDE3LjY1OTkyMzUsMTMuNjE0MzE5OSAxNy42NTk5MjM1LDguODg4ODg4ODkgQzE3LjY1OTkyMzUsNC4xNjM0NTc4NyAxMy44NjU3MjY0LDAuMzMyNzM5MTU2IDkuMTg1MzQ3MTgsMC4zMzI3MzkxNTYgTDkuMTg1MzQ3MTgsMTcuNDQ1MDM4NiBaIiBpZD0iT3ZhbC03Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0zNC42NTk3Mzg1LDI0LjgwOTY5NCBMNS43MTY2NjA4NCw0Ljc2ODc4OTQ1IiBpZD0iUGF0aC0yIiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMC45NDExNzY0NzEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8ZWxsaXBzZSBpZD0iT3ZhbCIgc3Ryb2tlPSIjQ0ZEQUU2IiBzdHJva2Utd2lkdGg9IjAuOTQxMTc2NDcxIiBjeD0iMy4yNjI3MTE4NiIgY3k9IjMuMjk0MTE3NjUiIHJ4PSIzLjI2MjcxMTg2IiByeT0iMy4yOTQxMTc2NSI+PC9lbGxpcHNlPgogICAgICAgICAgICAgICAgICAgIDxlbGxpcHNlIGlkPSJPdmFsLUNvcHkiIGZpbGw9IiNGN0UxQUQiIGN4PSIyLjc5NjYxMDE3IiBjeT0iNjEuMTc2NDcwNiIgcng9IjIuNzk2NjEwMTciIHJ5PSIyLjgyMzUyOTQxIj48L2VsbGlwc2U+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTM0LjYzMTI0NDMsMzkuMjkyMjcxMiBMNS4wNjM2NjY2Myw1OS43ODUwODIiIGlkPSJQYXRoLTEwIiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMC45NDExNzY0NzEiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxnIGlkPSJHcm91cC0xOSIgb3BhY2l0eT0iMC4zMyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTI4Mi41MzcyMTksIDQ0Ni41MDI4NjcpIHJvdGF0ZSgtMTAuMDAwMDAwKSB0cmFuc2xhdGUoLTEyODIuNTM3MjE5LCAtNDQ2LjUwMjg2NykgdHJhbnNsYXRlKDExNDIuNTM3MjE5LCAzMjcuNTAyODY3KSI+CiAgICAgICAgICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwLTE3IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNDEuMzMzNTM5LCAxMDQuNTAyNzQyKSByb3RhdGUoMjc1LjAwMDAwMCkgdHJhbnNsYXRlKC0xNDEuMzMzNTM5LCAtMTA0LjUwMjc0MikgdHJhbnNsYXRlKDEyOS4zMzM1MzksIDkyLjUwMjc0MikiIGZpbGw9IiNCQUNBRDkiPgogICAgICAgICAgICAgICAgICAgICAgICA8Y2lyY2xlIGlkPSJPdmFsLTQiIG9wYWNpdHk9IjAuNDUiIGN4PSIxMS42NjY2NjY3IiBjeT0iMTEuNjY2NjY2NyIgcj0iMTEuNjY2NjY2NyI+PC9jaXJjbGU+CiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMy4zMzMzMzMzLDIzLjMzMzMzMzMgQzIzLjMzMzMzMzMsMTYuODkwMDExMyAxOC4xMDk5ODg3LDExLjY2NjY2NjcgMTEuNjY2NjY2NywxMS42NjY2NjY3IEM1LjIyMzM0NDU5LDExLjY2NjY2NjcgMCwxNi44OTAwMTEzIDAsMjMuMzMzMzMzMyBMMjMuMzMzMzMzMywyMy4zMzMzMzMzIFoiIGlkPSJPdmFsLTQiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExLjY2NjY2NywgMTcuNTAwMDAwKSBzY2FsZSgtMSwgLTEpIHRyYW5zbGF0ZSgtMTEuNjY2NjY3LCAtMTcuNTAwMDAwKSAiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSBpZD0iT3ZhbC01LUNvcHktNiIgZmlsbD0iI0NGREFFNiIgY3g9IjIwMS44MzMzMzMiIGN5PSI4Ny41IiByPSI1LjgzMzMzMzMzIj48L2NpcmNsZT4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQzLjUsODguODEyNjY4NSBMMTU1LjA3MDUwMSwxNy42MDM4NTQ0IiBpZD0iUGF0aC0xNyIgc3Ryb2tlPSIjQkFDQUQ5IiBzdHJva2Utd2lkdGg9IjEuMTY2NjY2NjciPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTcuNSwzNy4zMzMzMzMzIEwxMjcuNDY2MjUyLDk3LjY0NDk3MzUiIGlkPSJQYXRoLTE4IiBzdHJva2U9IiNCQUNBRDkiIHN0cm9rZS13aWR0aD0iMS4xNjY2NjY2NyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwb2x5bGluZSBpZD0iUGF0aC0xOSIgc3Ryb2tlPSIjQ0ZEQUU2IiBzdHJva2Utd2lkdGg9IjEuMTY2NjY2NjciIHBvaW50cz0iMTQzLjkwMjU5NyAxMjAuMzAyMjgxIDE3NC45MzU0NTUgMjMxLjU3MTM0MiAzOC41IDE0Ny41MTA4NDcgMTI2LjM2Njk0MSAxMTAuODMzMzMzIj48L3BvbHlsaW5lPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTkuODMzMzMzLDk5Ljc0NTM4NDIgTDE5NS40MTY2NjcsODkuMjUiIGlkPSJQYXRoLTIwIiBzdHJva2U9IiNFMEI0QjciIHN0cm9rZS13aWR0aD0iMS4xNjY2NjY2NyIgb3BhY2l0eT0iMC42Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIwNS4zMzMzMzMsODIuMTM3MjEwNSBMMjM4LjcxOTQwNiwzNi4xNjY2NjY3IiBpZD0iUGF0aC0yNCIgc3Ryb2tlPSIjQkFDQUQ5IiBzdHJva2Utd2lkdGg9IjEuMTY2NjY2NjciPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMjY2LjcyMzQyNCwxMzIuMjMxOTg4IEwyMDcuMDgzMzMzLDkwLjQxNjY2NjciIGlkPSJQYXRoLTI1IiBzdHJva2U9IiNDRkRBRTYiIHN0cm9rZS13aWR0aD0iMS4xNjY2NjY2NyI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtNSIgZmlsbD0iI0MxRDFFMCIgY3g9IjE1Ni45MTY2NjciIGN5PSI4Ljc1IiByPSI4Ljc1Ij48L2NpcmNsZT4KICAgICAgICAgICAgICAgICAgICA8Y2lyY2xlIGlkPSJPdmFsLTUtQ29weS0zIiBmaWxsPSIjQzFEMUUwIiBjeD0iMzkuMDgzMzMzMyIgY3k9IjE0OC43NSIgcj0iNS4yNSI+PC9jaXJjbGU+CiAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSBpZD0iT3ZhbC01LUNvcHktMiIgZmlsbC1vcGFjaXR5PSIwLjYiIGZpbGw9IiNEMURFRUQiIGN4PSI4Ljc1IiBjeT0iMzMuMjUiIHI9IjguNzUiPjwvY2lyY2xlPgogICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtNS1Db3B5LTQiIGZpbGwtb3BhY2l0eT0iMC42IiBmaWxsPSIjRDFERUVEIiBjeD0iMjQzLjgzMzMzMyIgY3k9IjMwLjMzMzMzMzMiIHI9IjUuODMzMzMzMzMiPjwvY2lyY2xlPgogICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwtNS1Db3B5LTUiIGZpbGw9IiNFMEI0QjciIGN4PSIxNzUuNTgzMzMzIiBjeT0iMjMyLjc1IiByPSI1LjI1Ij48L2NpcmNsZT4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+); /* background-color: #112346; */ background-repeat: no-repeat; background-position: center right; background-size: 100%; } .login-container { border-radius: 10px; margin: 0px auto; width: 350px; padding: 30px 35px 15px 35px; background: #fff; border: 1px solid #eaeaea; text-align: left; box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1); } .title { margin: 0px auto 40px auto; text-align: center; color: #505458; } </style>
4. 後臺首頁AppMain.vue的建立
2.1 Container佈局容器
AppMain.vue
<template> <el-container class="main-container"> <el-aside v-bind:class="asideClass"> <LeftNav></LeftNav> </el-aside> <el-container> <el-header class="main-header"> <TopNav></TopNav> </el-header> <el-main class="main-center">Main</el-main> </el-container> </el-container> </template> <script> // 導入組件 import TopNav from '@/components/TopNav.vue' import LeftNav from '@/components/LeftNav.vue' // 導出模塊 export default { data(){ return{ asideClass : 'main-aside' } }, components:{ TopNav,LeftNav } }; </script> <style scoped> .main-container { height: 100%; width: 100%; box-sizing: border-box; } .main-aside-collapsed { /* 在CSS中,經過對某同樣式聲明! important ,能夠更改默認的CSS樣式優先級規則,使該條樣式屬性聲明具備最高優先級 */ width: 64px !important; height: 100%; background-color: #334157; margin: 0px; } .main-aside { width: 240px !important; height: 700px; background-color: #334157; margin: 0px; } .main-header, .main-center { padding: 0px; border-left: 2px solid #333; } </style>
2.2 TopNav
<template> <!-- <el-menu :default-active="activeIndex2" class="el-menu-demo" mode="horizontal" @select="handleSelect" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b"> <el-menu-item index="1">處理中心</el-menu-item> <el-submenu index="2"> <template slot="title">個人工做臺</template> <el-menu-item index="2-1">選項1</el-menu-item> <el-menu-item index="2-2">選項2</el-menu-item> <el-menu-item index="2-3">選項3</el-menu-item> <el-submenu index="2-4"> <template slot="title">選項4</template> <el-menu-item index="2-4-1">選項1</el-menu-item> <el-menu-item index="2-4-2">選項2</el-menu-item> <el-menu-item index="2-4-3">選項3</el-menu-item> </el-submenu> </el-submenu> <el-menu-item index="3" disabled>消息中心</el-menu-item> <el-menu-item index="4"><a href="https://www.ele.me" target="_blank">訂單管理</a></el-menu-item> </el-menu> --> <el-menu class="el-menu-demo" mode="horizontal" background-color="#334157" text-color="#fff" active-text-color="#fff"> <el-button class="buttonimg"> <img class="showimg" :src="collapsed?imgshow:imgsq" @click="doToggle()"> </el-button> <el-submenu index="2" class="submenu"> <template slot="title">超級管理員</template> <el-menu-item index="2-1">設置</el-menu-item> <el-menu-item index="2-2">我的中心</el-menu-item> <el-menu-item @click="exit()" index="2-3">退出</el-menu-item> </el-submenu> </el-menu> </template> <script> export default { data(){ return{ collapsed:false, imgsq:require('@/assets/img/sq.png'), imgshow:require('@/assets/img/show.png') } }, methods:{ doToggle (){ this.collapsed = !this.collapsed; this.$root.Bus.$emit("collapsed-side", this.collapsed); }, exit(){ this.$router.push({ path:'/Login' }) } } } </script> <style scoped> .el-menu-vertical-demo:not(.el-menu--collapse) { border: none; } .submenu { float: right; } .buttonimg { height: 60px; background-color: transparent; border: none; } .showimg { width: 26px; height: 26px; position: absolute; top: 17px; left: 17px; } .showimg:active { border: none; } </style>
注1:使用數據總線,在非父子的組件之間通訊,完成左側菜單摺疊
2.3 LeftNav
<template> <el-menu default-active="2" class="el-menu-vertical-demo" background-color="#334157" text-color="#fff" active-text-color="#ffd04b" :collapse="collapsed" > <!-- <el-menu default-active="2" :collapse="collapsed" collapse-transition router :default-active="$route.path" unique-opened class="el-menu-vertical-demo" background-color="#334157" text-color="#fff" active-text-color="#ffd04b"> --> <div class="logobox"> <img class="logoimg" src="../assets/img/logo.png" alt=""> </div> <el-submenu index="1"> <template slot="title"> <i class="el-icon-location"></i> <span>導航一</span> </template> <el-menu-item-group> <template slot="title">分組一</template> <el-menu-item index="1-1">選項1</el-menu-item> <el-menu-item index="1-2">選項2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="分組2"> <el-menu-item index="1-3">選項3</el-menu-item> </el-menu-item-group> <el-submenu index="1-4"> <template slot="title">選項4</template> <el-menu-item index="1-4-1">選項1</el-menu-item> </el-submenu> </el-submenu> <el-menu-item index="2"> <i class="el-icon-menu"></i> <span slot="title">導航二</span> </el-menu-item> <el-menu-item index="3" disabled> <i class="el-icon-document"></i> <span slot="title">導航三</span> </el-menu-item> <el-menu-item index="4"> <i class="el-icon-setting"></i> <span slot="title">導航四</span> </el-menu-item> </el-menu> </template> <script> export default { data(){ return{ collapsed:false } }, created(){ this.$root.Bus.$on('collapsed-side',(v)=>{ this.collapsed= v ; }) } } </script> <style> .el-menu-vertical-demo:not(.el-menu--collapse) { width: 240px; min-height: 400px; } .el-menu-vertical-demo:not(.el-menu--collapse) { border: none; text-align: left; } .el-menu-item-group__title { padding: 0px; } .el-menu-bg { background-color: #1f2d3d !important; } .el-menu { border: none; } .logobox { height: 40px; line-height: 40px; color: #9d9d9d; font-size: 20px; text-align: center; padding: 20px 0px; } .logoimg { height: 40px; } </style>
5. vue Bus總線
5.1 將一個空的Vue實例放到根組件下,全部的子組件都能調用
main.js
new Vue({
el: '#app',
router,
components: {
App
},
template: '<App/>',
data: {
//自定義的事件總線對象,用於父子組件的通訊
Bus: new Vue()
}
})
5.2 在A組件觸發事件
this.$root.Bus.$emit("事件名", 參數1, 參數2, ...);
注1:關鍵點-->this.$root
之前父子組件間觸發事件是:this.$emit("事件名", 參數1, 參數2, ...);
5.3 在B組件監聽事件
this.$root.Bus.$on("事件名", 回調函數);
注1:有時候會發生事件只被emit觸發了一次,可是回調函數卻被執行了屢次的現象。這種現象每每發生在頁面跳轉退出後從新進入的時候。
產生緣由:
this.$root.Bus.$on實際是向Bus容器中添加一個事件監聽器,當頁面跳轉時,原來的vue組件被註銷,可是原來vue組件向Bus容器中添加的事件監聽器並不會被移除。
所以,當下次進入這個vue組件對應的頁面時,執行到this.$root.Bus.$on時,又會向Bus容器中添加一個重複的事件監聽器,以此類推,
致使Bus容器中有不少個如出一轍的事件監聽器,從而致使事件只被觸發一次,可是回調函數被執行屢次的現象。
解決方案:
在vue組件的beforeDetory鉤子函數中將本vue組件往Bus容器中添加的事件監聽器所有手動移除。
//在vue對象的methods域中定義個函數專門移除事件監聽器
offxxxListener: function () {
this.$root.Bus.off("事件名");
this.$root.Bus.off("事件名");
this.$root.Bus.off("事件名");
},
//在vue對象的beforeDestroy鉤子中調用以上函數
beforeDestroy() {
this.offxxxListener();
},
注2::not(selector) 選擇器匹配每一個元素是否是指定的元素/選擇器。
附錄一:ES6新特性:使用export和import實現模塊化
詳情見資料「04 ES6新特性:使用export和import實現模塊化 - 方方和圓圓 - 博客園.mht」
附錄二:easy-mock
一個在線模擬後臺的數據平臺,經過官網註冊帳戶以後,你就能夠生成一個在線的API接口,而後經過ajax或者axios就能夠訪問這個接口了
若是前端開發人員不少,存在跨地區合做,交流困難,後端接口須要頻繁修改的話.這種寫法並不適合!
這時候推薦使用easy-mock.部署到本地內網後,就能夠和其餘前端後端小夥伴愉快地 共同維護mock數據和接口.
附錄三:
collaps:摺疊,collapsed,摺疊的過去分詞
Toggle:切換開關
---恢復內容結束---