admin管理员组文章数量:1530884
1 模板的路由配置
搭建后台管理系统项目路由,本项目需要配置四个路由
1.建立views文件夹,放置路由界面
<template>
<div>
<h1>我是一级路由404</h1>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>
2.建立router文件夹,配置路由
// 通过vue-router插件实现模板路由的配置
import { createRouter, createWebHashHistory } from 'vue-router';
import { constantRoute } from './routes';
// 创建路由器
let router = createRouter({
// 路由模式hash
// 这种模式会在 URL 中使用 # 来管理路由
history: createWebHashHistory(),
routes: constantRoute,
// 滚动行为
scrollBehavior() {
return {
left: 0,
top: 0
}
}
});
export default router;
// 对外暴露配置路由(常量路由)
export const constantRoute = [
{
// 登录路由
path: '/login',
component: () => import('@/views/login/index.vue'),
name: 'login'//命名路由
},
{
// 登录成功展示数据的路由
path: '/',
component: () => import('@/views/home/index.vue'),
name: 'layout'
},
{
// 404
path: '/404',
component: () => import('@/views/404/index.vue'),
name: '404'
},
{
path: '/:pathMatch(.*)*',
redirect: '/404',
name: 'Any'
}
]
3.在入口文件引入注册,
4.测试一下:
<template>
<div>
<router-view></router-view>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>
2.登录路由静态搭建
1.根据element-plus官网进行搭建
2.login/index.vue
vh 是视口高度单位(Viewport Height),其中 1vh 等于视口高度的1%。
:xs屏幕宽度小于768时
<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-input type="password" :prefix-icon="Lock" v-model="loginForm.password" show-password></el-input>
</el-form-item>
<el-form-item>
<el-button class="login_btn">登录</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 scoped lang="scss">
.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;//上下20,左右0
}
.login_btn{
width:100%;
}
}
}
</style>
3.收集账号密码
在开发者模式中使用vuedivtools插件,好查看是是否能手机数据:
在插件应用商城搜索该插件,并且选中开发者模式即可
3.模板封装登录业务
登录流程:发请求–输入账号密码–登录成功进入首页,登录失败给提示
如果用户登录成功,会返回用户信息token,根据token向服务器发请求,要这个人相应的数组
把token存储到pinia仓库中
3.1 配置仓库pinia
pnpm i pinia
在src/store文件夹下存放仓库文件
在入口文件maints引入仓库
有root显示表明有大仓库了
3.2用户仓库
建立src/store/modules 存放用户小仓库
// 创建用户相关的小仓库
import { defineStore } from 'pinia';
// 引入接口
import { reqLogin } from '@/api/user';
// 引入数据类型
import type { loginForm } from '@/api/user/type';
// 创建用户小仓库
let useUserStore = defineStore('User', {
// 小仓库存储数据的地方
state: () => {
return {
token: localStorage.getItem("TOKEN"),
}
},
// 异步|逻辑的地方
actions: {
// 用户登录的方法
async userLogin(data: loginForm) {
// 登录请求
let result:any = await reqLogin(data);
console.log(result);
// 登录请求:成功200--token
// 登录请求:失败201--登录失败的错误信息
if (result.code == 200) {
// pinia仓库存储一下token
// 由于pinia|vuex存储数据其实利用js对象
this.token = result.data.token;
// 本地存储持久化存储一份
localStorage.setItem("TOKEN", result.data.token);
// 能保证async函数能返回一个成功的promise
return 'ok';
} else {
return Promise.reject(new Error(result.data.message));
}
}
},
//
getters: {
}
});
// 对外暴露获取小仓库的方法
export default useUserStore;
TIPS:1.异步编程,async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果,async返回值是promise对象
详细异步编程解说:https://juejin/post/6844903776780828685
2.let 关键字,用于声明变量,仅在{}内有效,且let 声明的变量必须在声明之后才能被访问。与var不同,var 声明的变量具有函数作用域或被提升至全局作用域。
3.3 持久化存储token
后面要根据token找服务器要信息,所以要保证token持久化
现在的token一刷新就没有了
采用本地存储存储token,当然也可以用cookie封装
组件路由要知道自己登录情况是成功还是失败,如果成功,会有消息提示登录成功
async会返回promise对象,pending(等待),fulfilled(成功),rejected(失败)
src/views/login/index.ts
<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-input type="password" :prefix-icon="Lock" v-model="loginForm.password" show-password></el-input>
</el-form-item>
<el-form-item>
<el-button :loading="loading" type="primary" class="login_btn" @click="login">登录</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, ref } from 'vue';
import { useRouter } from 'vue-router';
import { ElNotification } from 'element-plus';
// 引入用户相关的小仓库
import useUserStore from '@/store/modules/user';
let useStore = useUserStore();
// 获取路由器
let $router = useRouter();
// 定义变量控制按钮加载效果
let loading = ref(false);
// 收集账号与密码的数据
let loginForm = reactive({ username: 'admin', password: '111111' })
// 登录按钮的回调
// 加载效果:开始加载
const login = async () => {
loading.value = true;
// 点击登录按钮以后干什么??
// 通知仓库发登录请求
// 请求成功--首页展示数据的地方
// 请求失败--弹出登录失败信息
try {
// 可以采用.then语法,我这里使用try catch语法
// 保证登录成功
// 请求失败,加载效果消失
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
});
}
}
</script>
<style scoped lang="scss">
.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; //上下20,左右0
}
.login_btn {
width: 100%;
}
}
}
</style>
TIPS:1.变量名前面的
符号通常是一个习惯用法,用来表示某些特别的、全局可用的或重要的对象,
符号通常是一个习惯用法,用来表示某些特别的、全局可用的或重要的对象,
符号通常是一个习惯用法,用来表示某些特别的、全局可用的或重要的对象,router 是一个变量名,这里使用 $ 是为了明确指出这个变量持有一个对Vue路由器实例的引用。
2.采用try(成功干嘛)catch(不成功干嘛)结构
3.类型断言:有两种断言方法1.as断言, message: (error as Error).message
告诉ts编译器error是Error对象,目的是为了能够安全地访问 Error 对象的 message 属性。如果没有这个断言,如果 error 的类型不确定(undefined),编译器可能会警告或错误,表示不确定 error 是否有 message 属性。2.<> 语法let strLength: number = (<string>someValue).length;
el消息提示组件elnotification
elbutton按钮 loading属性(加载现象)
TIPS:
1.ref是一个函数,用来创建一个响应式的引用对象,这个对象包含一个可以被Vue跟踪其变化的值。先给loading为ref(false)关闭状态,点击按钮把他变为true状态
2.可以点击开发者模式 network调节网速查看效果
3.4 用户仓库数据ts类型的定义
1.state函数返回的数据类型
上次state()返回对象类型直接定义为any
在modules新建文件types/type.ts存放定义类型文件
// 定义小仓库数据state类型
export interface UserState{
token:string|null;
}
将state()返回对象类型改为state:UserState()
2.定义登录接口返回的数据类型
let result: loginResponseData = await reqLogin(data);
interface dataType {
token?: string,
message?:string
}
// 登录接口返回数据类型
export interface loginResponseData {
code: number,
data: dataType
}
3.封装本地存储存数据和读数据的方法
将上述方法封装在utils/token.ts文件里面
// 封装本地存储数据和读取数据的方法
export const SET_TOKEN = (token: string) => {
localStorage.setItem("TOKEN", token);
}
export const GET_TOKEN = () => {
return localStorage.getItem('TOKEN');
}
在user.ts引入调用即可
state: (): UserState => {
return {
token: GET_TOKEN(),
}
},
// 异步|逻辑的地方
actions: {
// 用户登录的方法
async userLogin(data: loginForm) {
// 登录请求
let result: loginResponseData = await reqLogin(data);
console.log(result);
// 登录请求:成功200--token
// 登录请求:失败201--登录失败的错误信息
if (result.code == 200) {
// pinia仓库存储一下token
// 由于pinia|vuex存储数据其实利用js对象
this.token = (result.data.token as string);
// 本地存储持久化存储一份
SET_TOKEN((result.data.token as string));
// 能保证async函数能返回一个成功的promise
return 'ok';
3.5登录时间的判断与封装
使用内置函数Date获取当前时间
新建utils/time.ts文件
// 封装一个函数,获取一个结果:当前是早上|上午|下午|晚上
export const getTime = () => {
let message = '';
// 通过内置构造函数Date
let hours = new Date().getHours();
if (hours <= 9) {
message = '早上';
} else if (hours <= 12) {
message = '上午';
} else if (hours <= 18) {
message = '下午';
} else {
message = '晚上';
}
return message;
}
在login/index.vue改动
ElNotification({
type: 'success',
message: '欢迎回来',
title: `HI,${getTime()}好`
});
TIPS:
1.~ ~为模板字符串,使用反引号标记的字符串,模板字符串可以包含差值表达式${表达式},表达式的结果会被转换为字符串,并插入到模板字符串的相应位置。
4.登录模块表单校验
利用element-plus 里面form表单所提供的组件
1.给表单定义model属性,告诉表单我们数据收集到哪里
2.给表单添加规则rules
<el-form class="login_form" :model="loginForm" :rules="rules" ref="loginForms">
// 定义表单规则需要的配置对象
const rules = {
username: [
// trigger:触发校验时机,一般有两个,一个是blur(失去焦点)一个是change(当文本发生变化)
// required: true代表这个字段必填
// message:错误提示信息
// { required: true, message: '用户名不能为空', trigger: "blur" },
{ required: true, min: 6, max: 10, message: '账号长度至少为6位', trigger: "change" }
],
password: [
{ required: true, min: 6, max: 15, message: '密码长度至少为6位', trigger: "change" }
]
}
查看校验规则有没有生效
3.每个el-form-item对象添加prop属性
<el-form-item prop="username">
TIPS:vue3的ref是一个指令,接收的是一个变量而不是字符串
4.保证全部的表单项校验通过再发送请求
validate返回的是一个promise对象
await loginForms.value.validate();
4.1自定义校验表单
上述规则只能约束长度大小,不能做复杂的约束
使用自定义校验规则
1.写规则
const rules = {
username: [
// trigger:触发校验时机,一般有两个,一个是blur(失去焦点)一个是change(当文本发生变化)
// required: true代表这个字段必填
// message:错误提示信息
// { required: true, message: '用户名不能为空', trigger: "blur" },
// { required: true, min: 6, max: 10, message: '账号长度至少为6位', trigger: "change" }
{ trigger: 'change', validator: validatorUserName }
],
password: [
// { required: true, min: 6, max: 15, message: '密码长度至少为6位', trigger: "change" }
{ trigger: 'change', validator: validatorPassword }
]
const validatorPassword = (rule: any, value: any, callback: any) => {
// rule:即为校验规则对象
// value:即为表单元素的文本内容
// callback:函数,如果符合条件,callback放行即可
// 如果不符合条件,callback方法注入错误提示信息
// /^\d{5,10}$/.test(value)
if (value.length >= 6) {
callback();
} else {
callback(new Error('密码长度至少为6位'));
}
};
// 自定义校验规则需要的函数
const validatorUserName = (rule: any, value: any, callback: any) => {
// rule:即为校验规则对象
// value:即为表单元素的文本内容
// callback:函数,如果符合条件,callback放行即可
// 如果不符合条件,callback方法注入错误提示信息
// /^\d{5,10}$/.test(value)
if (value.length >= 5) {
callback();
} else {
callback(new Error('账号长度至少为5位'));
}
console.log(callback);
};
TIPS:关于正则表达式https://blog.csdn/saber04/article/details/100042797
边界字符 ^ $:
^ : 表示匹配行首的文本(从谁开始)
$ : 表示匹配行尾的文本(以谁结束)
test用于检测字符串是否符合规则,返回true/false
/^\d{5,10}$/
这个是5到10位的数字
5 一级路由组件静态搭建
该界面分三部分:左边导航区(展示菜单)顶部导航区 内容展示区(二级路由组件)
新建scr/layout/index.vue文件
<template>
<div class="layout_container">
<!-- 左侧菜单 -->
<div class="layout_slider">123</div>
<!-- 顶部导航 -->
<div class="layout_tabbar">456</div>
<!-- 内容展示区 -->
<div class="layout_main">
<p style="height: 10000px;background-color: aqua;">我是一个段落</p>
</div>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped lang="scss">
.layout_container {
width: 100%;
height: 100vh;
.layout_slider {
// 宽度写成全局变量可以随时改
width: $base-menu-width;
height: 100vh;
background-color: $base-menu-background;
}
.layout_tabbar {
position: fixed;
width: calc(100% - $base-menu-width);
height: $base-tabbar-height;
background-color: blue;
top: 0px;
left: $base-menu-width;
}
.layout_main {
position: absolute;
width: calc(100% - $base-menu-width);
height: calc(100vh - $base-tabbar-height);
background-color: white;
left:$base-menu-width;
top:$base-tabbar-height;
padding:20px;
overflow: auto;
}
}
</style>
将一些变量写成全局变量存放在styles/variable.scss文件夹中
// 左侧的菜单宽度
$base-menu-width:260px;
// 左侧菜单背景颜色
$base-menu-background:#001529;
// 顶部导航的高度
$base-tabbar-height:50px;
滚动条外观放置在styles/index.scss文件夹中
// 滚动条外观设置
::-webkit-scrollbar{
width: 10px;
}
::-webkit-scrollbar-track{
background-color: $base-menu-background;
}
::-webkit-scrollbar-thumb{
width:10px;
background-color: yellowgreen;
border-radius: 10px;
}
TIPS:$符号用于引用变量,可以重复利用数据
版权声明:本文标题:二、B站尚硅谷VUE项目硅谷甄选2 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1725660337a1035323.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论