1. 登錄
- 輸入用戶名、密碼
- 調用后台接口進行驗證
- 通過驗證后,根據響應狀態跳轉到項目主頁
- 通過cookie在客戶端記錄狀態【不存在跨域問題】
- 通過session在服務器端記錄狀態【不存在跨域問題】
- ★通過token方式維持狀態【存在跨域問題】
- token原理
- 通過Element-UI組件實現布局

- 字體引用
首先需要導入到main.js中
import './assets/fonts/iconfont.css'
<el-input prefix-icon="iconfont icon-user"></el-input>
- 重置按鈕
模板 ref=引用對象
<el-form ref="LoginFormRef">
<el-button @click="reset">重置</el-button>
<el-form>
<script>
export default {
methods: {
reset () {
this.$refs.LoginFormRef.resetFields()
}
}
}
</script>
- 發起登陸請求需要axios
導入axios包
import axios from 'axios'
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
Vue.prototype.$http = axios //掛載到Vue的原型對象上
出現Promise函數的話 就async await
this.$refs.loginFormRef.validate(async (valid) => {
if (!valid) { return };
const { data: res } = await this.$http.post('login', this.loginForm)
if (res.meta.status !== 200) return this.$message.error('登陸失敗')
this.$message.success('恭喜您,登陸成功!')
})
__{data:res}__解構賦值把data屬性單獨領出來,賦值給res
- 消息提示(彈窗)
導入
import { Message } from 'element-ui'
!!需要掛載!!
Vue.prototype.$message = Message
這樣做是因為可以每個組件就可以通過this.$message訪問這個彈窗提示
if (res.meta.status !== 200) return this.$message.error('登陸失敗')
this.$message.success('恭喜您,登陸成功!')
- 登錄成功過后的token保存在客戶端的SessionStorage中
window.sessionStorage.setItem('token', res.data.token)
- 通過
編程式導航【router】跳轉到后台主頁
this.$router.push('/home')
- 路由導航守衛控制訪問權限
就是不登錄 不能顯示登錄后的頁面,強制跳轉回登錄頁
- to將要訪問的路徑
- from從哪個路徑跳轉過來
- next()放行
- next('/login')強制跳轉
//為路由對象添加beforeEach導航守衛
router.beforeEach((to,from,next)=>{
//如果用戶從登錄頁登陸,直接放行
if(to.path==='/login') return next()
//從sessionStroage中獲取token值
const tk = window.sessionStorage.getItem('token')
//沒有token值,強制跳轉到登錄頁
if(!tk) return next('/login')
next()
})
2. 退出
只需要銷毀本地token值
//清空token值
window.sessionStorage.clear()
//跳轉到登錄頁
this.$router.push('/login')
3.主頁布局

<el-container>
//頭部區域
<el-header>Header</el-header>
<el-container>
//側邊欄區域
<el-aside width="200px">Aside</el-aside>
//主體區域
<el-main>Main</el-main>
</el-container>
</el-container>
-
左右布局(Flex)
- 左右貼邊對齊
display: flex; justify-content: space-between;(左右貼邊對齊) align-items: center;(上下居中對齊) -
嵌套Flex布局
- 圖片在el-header中已經進行flex布局,已經進行左右貼邊對齊justify-content: space-between;
- 文字旁邊的文字,想要達到與圖片居中對齊,可以設置字體span標簽的flex布局 在跟一個align-items: center; 居中對齊
.el-header { display: flex; justify-content: space-between;(左右貼邊對齊) align-items: center; > div { display: flex; align-items: center; } }
1. 左側菜單布局
- 菜單分為二級,可以折疊
slot是插槽
<el-menu>
<el-submenu>
//一級菜單
<i class="el-icon-menu"></i>
<span>一級菜單</span>
//在一級菜單中嵌套二級菜單
<el-menu-item>
<i class="el-icon-menu"></i>
<span slot="title">二級菜單</span>
</el-menu-item>
</el-submenu>
</el-menu>
-
通過接口獲取菜單數據
-
通過axios請求攔截器添加token,在掛載之前進行預處理
需要授權API,請求頭中使用authorization字段提供token【在請求的時候,進行預處理】
//axios預處理 //攔截器[interceptors]請求攔截器[request]掛在函數[use] axios.interceptors.request.use(config=>{ //添加token驗證的authorization字段 config.headers.Authorization = window.sessionStorage.getItem('token') return config })- 獲取所有菜單
<script> export default { data() { return { menuList: [] } }, // 頁面加載完成,就獲取數據 created() { this.getMenuList() }, methods: { async getMenuList() { // 解構賦值 const { data: res } = await this.$http.get('menus') if (res.meta.status !== 200) return this.$message.error(res.meta.msg) this.menuList = res.data console.log(res) } } }- UI繪制(雙重for循環)
//外層for循環渲染一級菜單 <el-submenu :index="item.id+''" v-for="item in menuList" :key="item.id"> <span>{{item.authName}}</span> //內層for循環渲染二級菜單 <el-menu-item :index="subitem.id+''" v-for="subitem in item.children" :key="subitem.id"> <span>{{subitem.authName}}</span>-
每一個一級菜單 文字前面的圖標不同
- 解決方案:
- 因為每個一級菜單是通過for循環自動生成,修改圖標 是利用對象的鍵值對來解決
- 每一項的id作為key,值作為圖標
// 一級菜單圖標動態變化 <i :class="iconList[item.id]"></i> data () { return { // 導航欄數據 menuList: [], iconList: { 125: 'iconfont icon-user', 103: 'iconfont icon-tijikongjian', 101: 'iconfont icon-shangpin', 102: 'iconfont icon-danju', 145: 'iconfont icon-baobiao' } } }, - 解決方案:
-
每個邊框線沒有對齊,有瑕疵
-
用調試工具查看,可以看到是el-menu有邊框的問題,變成none即可
.el-menu { border: none; }
-
-
字間距:
letter-spacing:0.2em -
SPA,單頁面模式,在指定的區域顯示不同的內容(路由占位符)
-
在父路由(index)下設置一個children子路由規則,嵌套顯示一個(Welcome)組件
-
新建一個Welcome的vue文件
-
在router的index.js中設置 ⭐children屬性是一個數組
const routes = [ { path: '/index', component: index, redirect: '/welcome', children: [{ path: '/welcome', component: welcome }] } ] -
在index父級文件中填寫路由占位符
-
-
為每一個菜單增加點擊router事件
- 為整個側邊欄開啟路由模式[是否使用 vue-router 的模式,啟用該模式會在激活導航時以 index 作為 path 進行路由跳轉]
<el-menu :router="true"></el-menu> -
