网站首页 > 技术文章 正文
以前用react写过一个登录页面,不过实际工作中还是决定使用vue进行开发,这里就再记录一次用vue3实现一个登录页面。
演示准备
还是采用VSCode,暂时就个人感受来讲,免费的前端编程ide中,VSCode应该是首选。安装一下npm、pnpm,准备一些后端接口,可以用mock,或者随便找点后端框架写一点,我是用python flask在本地弄了一些需要的接口。
实操演示-创建工程
到工作目录打开cmd界面,通过命令新建一个vue项目工程:
npm create vue@latest然后就是根据提示选择是否添加组件:
项目虽然创建成功了,但是里面是没有引入各种资源库的,需要通过命令安装一下:
此时可以通过命令启动这个新建的项目:
可以通过浏览器访问:
界面能正常显示出来,就表示项目创建成功。
实操演示-依赖库添加
先添加sass,这个库可以让我们更灵活的写css,我自己不算是前端开发,写css其实不是很频繁,但是看其他几个前端开发都挺喜欢用sass的。
通过命令添加:
再添加一个axios,这个是用来请求后端接口的:
最后再加一个element-plus,做这个登录页面,用不用element-plus都可以,可以根据自己喜好添加element-plus或者ant-design-vue都可以,都是类似功能的组件。
实操演示-清理不需要的内容
将新建项目时自动带入的一些组件、图片、样式文件等删除:
这些删除的文件在留存的代码中有对应的引用,也删除一下,可以通过运行项目,看哪边报错,找对应位置进行修改:
还有些比较复杂的,可以直接清除原内容,还原成一些基础代码,比如App.vue:
网上找一个reset.scss(npm的官网上就有),清除当前所有默认样式:
引用这个reset.scss:
这里的@路径别称是项目创建时自动配置的,可以在vite.config.ts中看到:
实操演示-静态结构搭建
如果刚开始没什么思路,可以到element-plus的官网上抄类似的代码:
只需要在外层配一个背景,改一下参数名称,其实就可以用了。
因为从element-plus上抄了代码,所以要配置对应的样式,和使用对应的组件:
我为了和后面登录效果做铺垫,先在App.vue中加一个路由组件:
因为要使用路由,所以要在main.tx中使用路由模块:
配置路由信息:
要写一个登录页面:
<script setup lang="ts">
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
import { ref, reactive } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter()
const url = ref('/images/favicon.ico')
const fit = 'scale-down'
const boxbg = ref('/images/login-box-bg.svg')
const form = reactive({
    userName: '',
    passWord: ''
})
const rules = reactive<FormRules>({
    userName: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
    passWord: [{ required: true, message: '请输入密码', trigger: 'blur' }]
})
const ruleFormRef = ref<FormInstance>()
const onSubmit = async (ruleFormRef: FormInstance | undefined) => {
    if (!ruleFormRef) return;
    await ruleFormRef.validate(async (valid, fields) => {
        if (valid) {
            // 这里要调用后端接口,根据后端返回的值,决定是否走后面的路由进入系统内部
            router.push({ path: '/desktop' });
        } else {
            let errors: string = "";
            fields?.userName?.forEach(element => {
                errors += element.message + '; '
            })
            fields?.passWord?.forEach(element => {
                errors += element.message + '; '
            })
            ElMessage({
                type: "warning",
                message: errors
            })
        }
    })
}
</script>
<template>
    <div class="login">
        <div class="relative">
            <div class="left">
                <el-row>
                    <el-col :span="24">
                        <div class="homepageLogo">
                            <ul>
                                <li>
                                    <el-image style="width: 50px; height: 40px;" :src="url" :fit="fit" />
                                </li>
                                <li><span>Allure System</span></li>
                            </ul>
                        </div>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col>
                        <el-image class="boxgb" :src="boxbg" :fit="fit" />
                        <p class="p1">欢迎使用本系统</p>
                        <p class="p2">一个很潦草的后端管理系统</p>
                    </el-col>
                </el-row>
            </div>
            <div class="right">
                <el-row>
                    <el-col :span="24">
                        <h2>登录</h2>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="24">
                        <el-form :model="form" label-width="120px" label-position="top" size="large" class="form"
                            :rules="rules" ref="ruleFormRef">
                            <el-form-item label="用户名" prop="userName">
                                <el-input v-model="form.userName"></el-input>
                            </el-form-item>
                            <el-form-item label="密码" prop="passWord">
                                <el-input v-model="form.passWord" type="password" show-password></el-input>
                            </el-form-item>
                            <el-form-item>
                                <el-button class="submitBtn" type="primary" @click="onSubmit(ruleFormRef)">登录</el-button>
                            </el-form-item>
                        </el-form>
                    </el-col>
                </el-row>
            </div>
        </div>
    </div>
</template>
<style lang="scss" scoped>
.login {
    width: 100%;
    height: 100%;
    .relative {
        width: 100%;
        height: 100%;
        text-align: center;
        .left {
            width: 50%;
            height: 100%;
            float: left;
            background-image: url('/images/login-bg.jpg');
            .boxbg {
                width: 350px;
                height: 350px;
                margin-top: 100px;
            }
            .homepageLogo {
                height: 50px;
                line-height: 50px;
                margin-top: 40px;
                margin-left: 40px;
                span {
                    color: white;
                    font-size: 24px;
                }
                ul {
                    list-style: none;
                    li {
                        float: left;
                        margin-left: 5px;
                    }
                }
            }
            p {
                color: white;
            }
            .p1 {
                font-size: 1.875rem;
                line-height: 2.825rem;
            }
            .p2 {
                font-size: 0.875rem;
                line-height: 1.25rem;
            }
        }
        .right {
            width: 50%;
            float: left;
            padding-top: 15%;
            .form {
                width: 50%;
                margin: 0px auto;
                .submitBtn {
                    width: 100%;
                }
            }
        }
    }
}
</style>实现效果就是这样:
实操演示-后端交互封装
使用axios封装一下filter.ts:
//导入axios
import axios from 'axios'
import { ElMessage } from 'element-plus'
//创建一个axios实例 
const instance = axios.create({
    withCredentials: true,
    headers: {
        'content-type': 'application/json,text/plain,*/*'
    },
    // withCredentials: true,
    timeout: 5000  //5秒
})
instance.interceptors.request.use(
    config => {
        return config
    },
    error => {
        ElMessage.error("遇到报错:", error)
    }
)
//http 拦截器
instance.interceptors.response.use(
    response => {
        console.log(response.data)
        //拦截请求,统一相应
        if (response.data.isSuccess) {
            return response.data.result
        } else {
            ElMessage.error(response.data.msg)
            return response.data.result
        }
    },
    //error也可以处理
    error => {
        console.log(error)
        if (error.response) {
            switch (error.response.status) {
                case 401:
                    ElMessage.warning("资源没有访问权限!")
                    break
                case 404:
                    ElMessage.warning("接口不存在,请检查接口地址是否正确!")
                    break
                case 500:
                    ElMessage.warning("内部服务器错误,请联系系统管理员!")
                    break
                default:
                    return Promise.reject(error.response.data)   // 返回接口返回的错误信息 
            }
        }
        else {
            ElMessage.error("遇到跨域错误,请设置代理或者修改后端允许跨域访问!")
        }
    }
)
export default instance在根据上面封装的filter.ts,写一下获取token的请求:
//需要拦截器的地方使用instance对象, 有自定义返回逻辑的地方沿用axios,在组件内部处理返回结果即可
import instance from './filter'
const http = "/api";
//获取token
export const getToken = (name: string, password: string) => {
    return instance.get(http + "/Login/GetToken?name=" + name + "&password=" + password);
}应该会遇到跨域问题,所以上面没有写具体url,到vite.config.ts中配置代理:
回到LoginPage.vue,调用getToken方法:
这个token是我随便写的,正常的需要经过一些转换才能读取其中的信息。
如果token中还有其他信息,也可以存储到本地cookie中,当然如果token要被经常使用到,也可以直接将token持久化,比如这样:
总结
一个潦草的登录模块就这样做好了。当然一个完整的登录模块,还有很多鉴权、路由控制等很多功能,这里就不展开了。
猜你喜欢
- 2025-01-21 SpringBoot与Vue交互解决跨域问题「亲测已解决」
- 2025-01-21 细解跨域以及跨域的解决方案
- 2025-01-21 52、Vue 怎么实现跨域(必会)
- 2025-01-21 聊聊axios-axios的介绍以及请求方式
- 2025-01-21 跨域请求如何携带cookie?不小心都拿了Offer
- 2025-01-21 前后端分离session问题
- 2025-01-21 springboot+security后端与前端需要注意的withCredentials设置
- 最近发表
- 
- 聊一下 gRPC 的 C++ 异步编程_grpc 异步流模式
- [原创首发]安全日志管理中心实战(3)——开源NIDS之suricata部署
- 超详细手把手搭建在ubuntu系统的FFmpeg环境
- Nginx运维之路(Docker多段构建新版本并增加第三方模
- 92.1K小星星,一款开源免费的远程桌面,让你告别付费远程控制!
- Go 人脸识别教程_piwigo人脸识别
- 安卓手机安装Termux——搭建移动服务器
- ubuntu 安装开发环境(c/c++ 15)_ubuntu安装c++编译器
- Rust开发环境搭建指南:从安装到镜像配置的零坑实践
- Windows系统安装VirtualBox构造本地Linux开发环境
 
- 标签列表
- 
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (87)
- localstorage.removeitem (77)
- vector线程安全吗 (73)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)
 
