1.路由配置
1.1路由組件的雛形
src\views\home\index.vue
(以home組件為例)
安裝插件:?
1.2路由配置
1.2.1路由index文件
src\router\index.ts
?//通過vue-router插件實現模板路由配置
import { createRouter, createWebHashHistory } from 'vue-router'
import { constantRoute } from './router'
//創建路由器
const router = createRouter({
? //路由模式hash
? history: createWebHashHistory(),
? routes: constantRoute,
? //滾動行為
? scrollBehavior() {
? ? return {
? ? ? left: 0,
? ? ? top: 0,
? ? }
? },
})
export default router
1.2.2路由配置
src\router\router.ts
//對外暴露配置路由(常量路由)
export const constantRoute = [
? {
? ? //登錄路由
? ? path: '/login',
? ? component: () => import('@/views/login/index.vue'),
? ? name: 'login', //命名路由
? },
? {
? ? //登錄成功以后展示數據的路由
? ? path: '/',
? ? component: () => import('@/views/home/index.vue'),
? ? name: 'layout',
? },
? {
? ? path: '/404',
? ? component: () => import('@/views/404/index.vue'),
? ? name: '404',
? },
? {
? ? //重定向
? ? path: '/:pathMatch(.*)*',
? ? redirect: '/404',
? ? name: 'Any',
? },
]
?
1.3路由出口
src\App.vue
?
2.登錄模塊
2.1 登錄路由靜態組件(布局)
src\views\login\index.vue
<template><div class="login_container"><el-row><el-col :span="12" :xs="0"></el-col><el-col :span="12" :xs="24"><el-form class="login_form"><h1>Hello</h1><h2>歡迎來到硅谷甄選</h2><el-form-item><el-input:prefix-icon="User"v-model="loginForm.username"></el-input></el-form-item><el-form-item><el-inputtype="password":prefix-icon="Lock"v-model="loginForm.password"show-password></el-input></el-form-item><el-form-item><el-button class="login_btn" type="primary" size="default">登錄</el-button></el-form-item></el-form></el-col></el-row></div>
</template><script setup lang="ts">import { User, Lock } from '@element-plus/icons-vue'import { reactive } from 'vue'//收集賬號與密碼數據let loginForm = reactive({ username: 'admin', password: '111111' })
</script><style lang="scss" scoped>.login_container {width: 100%;height: 100vh;background: url('@/assets/images/background.jpg') no-repeat;background-size: cover;.login_form {position: relative;width: 80%;top: 30vh;background: url('@/assets/images/login_form.png') no-repeat;background-size: cover;padding: 40px;h1 {color: white;font-size: 40px;}h2 {color: white;font-size: 20px;margin: 20px 0px;}.login_btn {width: 100%;}}}
</style>
注意:
- el-col是24份的,在此左右分為了12份。我們在右邊放置我們的結構。
:xs="0"
是為了響應式。el-form
下的element-plus元素都用el-form-item
包裹起來。?- 通過?
row
?(行)和?col
?(列)組件,并通過 col 組件的?span
?屬性我們就可以自由地組合布局。row
?行提供?gutter
?屬性來指定列之間的間距,其默認值為0。- 通過制定 col 組件的?
offset
?屬性可以指定分欄偏移的欄數。- 參照了 Bootstrap 的 響應式設計,預設了五個響應尺寸:xs、sm、md、lg 和 xl。
2.2 登陸業務實現
2.2.1 登錄按鈕綁定回調
?
回調應該做的事情?
const login = ?() => {
? //點擊登錄按鈕以后干什么
? //通知倉庫發起請求
? //請求成功->路由跳轉
? //請求失敗->彈出登陸失敗信息
}?
2.2.2 倉庫store初始化
- 大倉庫(筆記只寫一次)
安裝pinia:pnpm i pinia@2.0.34
src\store\index.ts
//創建用戶相關的小倉庫
import { defineStore } from 'pinia'
//創建用戶小倉庫
const useUserStore = defineStore('User', {
? //小倉庫存儲數據地方
? state: () => {},
? //處理異步|邏輯地方
? actions: {},
? getters: {},
})
//對外暴露小倉庫
export default useUserStore
?
2.2.3 按鈕回調
//登錄按鈕的回調
const login = async () => {
? //按鈕加載效果
? loading.value = true
? //點擊登錄按鈕以后干什么
? //通知倉庫發起請求
? //請求成功->路由跳轉
? //請求失敗->彈出登陸失敗信息
? try {
? ? //也可以書寫.then語法
? ? await useStore.userLogin(loginForm)
? ? //編程式導航跳轉到展示數據的首頁
? ? $router.push('/')
? ? //登錄成功的提示信息
? ? ElNotification({
? ? ? type: 'success',
? ? ? message: '登錄成功!',
? ? })
? ? //登錄成功,加載效果也消失
? ? loading.value = false
? } catch (error) {
? ? //登陸失敗加載效果消失
? ? loading.value = false
? ? //登錄失敗的提示信息
? ? ElNotification({
? ? ? type: 'error',
? ? ? message: (error as Error).message,
? ? })
? }
}
2.2.4 用戶倉庫?
//創建用戶相關的小倉庫
import {defineStore} from "pinia";
// 引入接口
import {reqLogin} from "../../api/user";
//引入數據類型
import type {loginForm} from '@/api/user/type'
//創建用戶小倉庫
const useUserStore = defineStore('User', {
小倉庫存儲數據地方
state: () => {
return {
token: localStorage.getItem('TOKEN')//用戶的唯一標識
}
},
//處理異步|邏輯地方
actions: {
async userLogin(data: loginForm) {
//登陸的請求
async
userLogin(data
:
loginForm
)
{
//登陸的請求
const result: any = await reqLogin(data)
if (result.code == 200) {
this.token = result.data.token
localStorage.setItem('TOKEN', result.data.token)
return 'ok'
} else {
return Promise.reject(new Error(result.data.message))
}
}
}
},
getters: {},
})
export default useUserStore
?2.2.5 小結
- Element-plus中ElNotification用法(彈窗):
引入:import { ElNotification } from 'element-plus'
使用:
//登錄失敗的提示信息
? ? ElNotification({
? ? ? type: 'error',
? ? ? message: (error as Error).message,
? ? })
- Element-plus中el-button的loading屬性。
- pinia使用actions、state的方式和vuex不同:需要引入函數和創建實例
- $router的使用:也需要引入函數和創建實例
- 在actions中使用state的token數據:this.token
- 類型定義需要注意。
- promise的使用和vue2現在看來是一樣的
?2.3模板封裝登陸業務
2.3.1 result返回類型封裝
?src\api\user\type.ts
interface dataType {
? token?: string
? message?: string
}//登錄接口返回的數據類型
export interface loginResponseData {
? code: number
? data: dataType
}
2.3.2 State倉庫類型封裝?
src\store\modules\types\type.ts
?//定義小倉庫數據state類型
export interface UserState {
? token: string | null
}
2.3.3 本地存儲封裝
將本地存儲的方法封裝到一起
?src\utils\token.ts
//封裝本地存儲存儲數據與讀取數據方法
export const SET_TOKEN = (token: string) => {
? localStorage.setItem('TOKEN', token)
}export const GET_TOKEN = () => {
? return localStorage.getItem('TOKEN')
}
?
2.4 登錄時間的判斷
- 封裝函數
?src\utils\time.ts
//封裝函數:獲取當前時間段
export const getTime = () => {
? let message = ''
? //通過內置構造函數Date
? const hour = new Date().getHours()
? if (hour <= 9) {
? ? message = '早上'
? } else if (hour <= 14) {
? ? message = '上午'
? } else if (hour <= 18) {
? ? message = '下午'
? } else {
? ? message = '晚上'
? }
? return message
}
?
2.5 表單校驗規則
2.5.1 表單校驗
- 表單綁定項
?
- 表單元素綁定項
Form 組件提供了表單驗證的功能,只需為 rules 屬性傳入約定的驗證規則,并將 form-Item 的 prop 屬性設置為需要驗證的特殊鍵值即可
?
- 使用規則rules
?
//定義表單校驗需要的配置對象
const rules = {
? username: [
? ? //規則對象屬性:
? ? {
? ? ? required: true, // required,代表這個字段務必要校驗的
? ? ? min: 5, //min:文本長度至少多少位
? ? ? max: 10, // max:文本長度最多多少位
? ? ? message: '長度應為6-10位', // message:錯誤的提示信息
? ? ? trigger: 'change', //trigger:觸發校驗表單的時機 change->文本發生變化觸發校驗, blur:失去焦點的時候觸發校驗規則
? ? },?
? ??
? ],
? password: [
? ?{
? ? ? required: true,
? ? ? min: 6,
? ? ? max: 10,
? ? ? message: '長度應為6-15位',
? ? ? trigger: 'change',
? ? },?
? ],
}
- 校驗規則通過后運行
?const login = async () => {
? //保證全部表單項校驗通過
? await loginForms.value.validate()
?? ?。。。。。。
}
2.5.2自定義表單校驗
- 修改使用規則rules
使用自己編寫的函數作為規則校驗。
//定義表單校驗需要的配置對象
const rules = {
? username: [
? ? //規則對象屬性:
? ? /* {
? ? ? required: true, // required,代表這個字段務必要校驗的
? ? ? min: 5, //min:文本長度至少多少位
? ? ? max: 10, // max:文本長度最多多少位
? ? ? message: '長度應為6-10位', // message:錯誤的提示信息
? ? ? trigger: 'change', //trigger:觸發校驗表單的時機 change->文本發生變化觸發校驗, blur:失去焦點的時候觸發校驗規則
? ? }, */
? ? { trigger: 'change', validator: validatorUserName },
? ],
? password: [
? ? { trigger: 'change', validator: validatorPassword },
? ],
}
- 自定義校驗規則函數
//自定義校驗規則函數
const validatorUserName = (rule: any, value: any, callback: any) => {
? //rule:校驗規則對象
? //value:表單元素文本內容
? //callback:符合條件,callback放行通過,不符合:注入錯誤提示信息
? if (value.length >= 5) {
? ? callback()
? } else {
? ? callback(new Error('賬號長度至少5位'))
? }
}const validatorPassword = (rule: any, value: any, callback: any) => {
? if (value.length >= 6) {
? ? callback()
? } else {
? ? callback(new Error('密碼長度至少6位'))
? }
}
3. Layout模塊(主界面)
3.1 組件的靜態頁面
3.1.1 組件的靜態頁面
注意:我們將主界面單獨放一個文件夾(頂替原來的home路由組件)。注意修改一下路由配置
?src\layout\index.vue
<template>
? <div class="layout_container">
? ? <!-- 左側菜單 -->
? ? <div class="layout_slider"></div>
? ? <!-- 頂部導航 -->
? ? <div class="layout_tabbar"></div>
? ? <!-- 內容展示區域 -->
? ? <div class="layout_main">
? ? ? <p style="height: 1000000px"></p>
? ? </div>
? </div>
</template><script setup lang="ts"></script>
<style lang="scss" scoped>
.layout_container {
? width: 100%;
? height: 100vh;
? .layout_slider {
? ? width: $base-menu-width;
? ? height: 100vh;
? ? background: $base-menu-background;
? }
? .layout_tabbar {
? ? position: fixed;
? ? width: calc(100% - $base-menu-width);
? ? height: $base-tabbar-height;
? ? background: cyan;
? ? top: 0;
? ? left: $base-menu-width;
? }
? .layout_main {
? ? position: absolute;
? ? width: calc(100% - $base-menu-width);
? ? height: calc(100vh - $base-tabbar-height);
? ? background-color: yellowgreen;
? ? left: $base-menu-width;
? ? top: $base-tabbar-height;
? ? padding: 20px;
? ? overflow: auto;
? }
}
</style>
?
?
3.1.2定義部分全局變量&滾動條
scss全局變量
src\styles\variable.scss?
//左側菜單寬度
$base-menu-width :260px;
//左側菜單背景顏色
$base-menu-background: #001529;//頂部導航的高度
$base-tabbar-height:50px;?
滾動條?
src\styles\index.scss
//滾動條外觀設置
::-webkit-scrollbar{
? width: 10px;
}::-webkit-scrollbar-track{
? background: $base-menu-background;
}::-webkit-scrollbar-thumb{
? width: 10px;
? background-color: yellowgreen;
? border-radius: 10px;
}
?3.2 Logo子組件的搭建
頁面左上角的這部分,我們將它做成子組件,并且封裝方便維護以及修改。
3.2.1 Logo子組件
在這里我們引用了封裝好的setting
src\layout\logo\index.vue
<template>
? <div class="logo" v-if="setting.logoHidden">
? ? <img :src="setting.logo" alt="" />
? ? <p>{{ setting.title }}</p>
? </div>
</template><script setup lang="ts">
? //引入設置標題與logo配置文件
? import setting from '@/setting'
</script><style lang="scss" scoped>
? .logo {
? ? width: 100%;
? ? height: $base-menu-logo-height;
? ? color: white;
? ? display: flex;
? ? align-items: center;
? ? padding: 20px;
? ? img {
? ? ? width: 40px;
? ? ? height: 40px;
? ? }
? ? p {
? ? ? font-size: $base-logo-title-fontSize;
? ? ? margin-left: 10px;
? ? }
? }
</style>
?
3.2.2 封裝setting
為了方便我們以后對logo以及標題的修改。
?//用于項目logo|標題配置
export default {
? title: '硅谷甄選運營平臺', //項目的標題
? logo: '/public/logo.png', //項目logo設置
? logoHidden: true, //logo組件是否隱藏
}
3.2.3 使用
在layout組件中引入并使用
?
3.3 左側菜單組件
3.3.1靜態頁面(未封裝)
主要使用到了element-plus的menu組件。附帶使用了滾動組件
src\layout\index.vue
?<!-- 左側菜單 -->
<div class="layout_slider">
? <Logo></Logo>
? <!-- 展示菜單 -->
? <!-- 滾動組件 -->
? <el-scrollbar class="scrollbar">
? ? <!-- 菜單組件 -->
? ? <el-menu background-color="#001529" text-color="white">
? ? ? <el-menu-item index="1">首頁</el-menu-item>
? ? ? <el-menu-item index="2">數據大屏</el-menu-item>
? ? ? <!-- 折疊菜單 -->
? ? ? <el-sub-menu index="3">
? ? ? ? <template #title>
? ? ? ? ? <span>權限管理</span>
? ? ? ? </template>
? ? ? ? <el-menu-item index="3-1">用戶管理</el-menu-item>
? ? ? ? <el-menu-item index="3-2">角色管理</el-menu-item>
? ? ? ? <el-menu-item index="3-3">菜單管理</el-menu-item>
? ? ? </el-sub-menu>
? ? </el-menu>
? </el-scrollbar>
</div>
3.3.2 遞歸組件生成動態菜單
在這一部分,我們要根據路由生成左側的菜單欄??
?
- 動態菜單子組件:src\layout\menu\index.vue
- 根據路由生成左側的菜單欄
- 處理路由--->因為我們要根據路由以及其子路由作為我們菜單的一級|二級標題。因此我們要獲取路由信息。
? ? ? ? ? ?給路由中加入了路由元信息meta:它包含了2個屬性:title以及hidden?
? ? 4.倉庫引入路由并對路由信息類型聲明(vue-router有對應函數)
? ?5. 父組件拿到倉庫路由信息并傳遞給子組件
? ?6.子組件prps接收并且處理結構
注意:
1:因為每一個項我們要判斷倆次(是否要隱藏,以及子組件個數),所以在el-menu-item外面又套了一層模板
2:當子路由個數大于等于一個時,并且或許子路由還有后代路由時。這里我們使用了遞歸組件。遞歸組件需要命名(另外使用一個script標簽,vue2格式)。