当前位置: 首页 > news >正文

开始尝试从0写一个项目--前端(一)

基础项目构建

创建VUE初始工程

确保自己下载了node.js和npm

node -v     //查看node.js的版本
npm -v      //查看npm的版本
npm i @vue/cli -g    //安装VUE CLI

创建

以管理员身份运行

输入:vue ui

就会进入

点击创建

自定义项目名字,选择npm管理

结构

用vscode打开这个项目

运行

打开终端

快捷键:ctrl+j

输入npm run serve回车

然后进入给的网址

修改端口

vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,devServer: {port: 8181}
})

现在我们就是在这个界面开始编写我们的代码

2024.7.4


学生登录界面

参考这篇文章

Vue 实现登录注册功能(前后端分离完整案例) | 软件研会

参考文章中遇到的一些问题

问题:解决error: Component name “xxx” should always be multi-word.

解决:

解决error: Component name “xxx” should always be multi-word._error component name "about" should always be mult-CSDN博客

问题:import VueAxios from 'vue-axios'中vue-axios找不到报错

解决:

npm i vue-axios

问题:点击登录之后,一直网页报错

解决措施:(麻了,我各种翻阅资料,居然是这里出错了,气死了!!!!!!!花费了我2小时)

src\views\login\Login.vue

问题基本搞定,还有一些小细节:

我们不需要注册这个版本,所以我没有搞。

基本就ok了

所有的代码:

src\App.vue


<template><div id="app"><router-view/></div>
</template><script>export default {name: 'App',components: {}
}
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;
}
</style>

src\main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'import router from './router'      //路由 2
import VueRouter from 'vue-router' // 路由 1import ElementUI from 'element-ui';	// Element 1
import 'element-ui/lib/theme-chalk/index.css'; // Element 2import axios from 'axios'  
import VueAxios from 'vue-axios'// 关闭 Vue 的生产提示
Vue.config.productionTip = false// 使用插件
Vue.use(ElementUI); // Element 3
Vue.use(VueRouter) // 路由 3
Vue.use(VueAxios, axios) // 使用 axios 插件// 创建 Vue 实例对象
new Vue({router,store,render: h => h(App)
}).$mount('#app')

vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,lintOnSave: false,devServer: {port: 8181,// 代理服务器可以将路由中的指定前缀转发到指定的后端服务器中proxy: {'/api': {target: 'http://localhost:8080',ws: true, // 是否启用websocketschangeOrigin: true,  // 代理时是否更改hostpathRewrite: {'^/api': '' //这里理解成用'/api'代替target里面的地址}}}}
})

src\views\login\Login.vue

<template><div><el-card class="box-card"><h2>登录</h2><el-form:model="ruleForm"status-icon:rules="rules"ref="ruleForm"label-position="left"label-width="70px"class="login-from"><el-form-item label="用户名" prop="username"><el-input v-model="ruleForm.username"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-inputtype="password"v-model="ruleForm.password"autocomplete="off"></el-input></el-form-item></el-form><div class="btnGroup"><el-buttontype="primary"@click="submitForm('ruleForm')"v-loading="loading">登录</el-button><el-button @click="resetForm('ruleForm')">重置</el-button><router-link to="/register"><el-button style="margin-left: 10px">注册</el-button></router-link></div></el-card></div>
</template><script>export default {data() {return {ruleForm: {username: "",password: "",},rules: {username: [{ required: true, message: "用户名不能为空!", trigger: "blur" },],password: [{ required: true, message: "密码不能为空!", trigger: "blur" },],},loading: false, // 是否显示加载动画};},methods: {submitForm(formName) {// 验证表单中的账号密码是否有效,因为在上面rules中定义为了必填 required: truethis.$refs[formName].validate((valid) => {// 点击登录后,让登录按钮开始转圈圈(展示加载动画)this.loading = true;// 如果经过校验,账号密码都不为空,则发送请求到后端登录接口if (valid) {let _this = this;// 使用 axios 将登录信息发送到后端this.axios({url: "/api/admin/student/login",               // 请求地址method: "post",                       // 请求方法headers: {                            // 请求头"Content-Type": "application/json",},data: {                             // 请求参数username: _this.ruleForm.username,password: _this.ruleForm.password,},}).then((res) => { // 当收到后端的响应时执行该括号内的代码,res 为响应信息,也就是后端返回的信息if (res.data.code === 1) {  // 当响应的编码为 1 时,说明登录成功// 将用户信息存储到sessionStorage中sessionStorage.setItem("userInfo", JSON.stringify(res.data.data));// 跳转页面到首页this.$router.push('/home');// 显示后端响应的成功信息this.$message({message: res.data.data,type: "success",});} else {  // 当响应的编码不为 1 时,说明登录失败// 显示后端响应的失败信息this.$message({message: res.data.msg,type: "warning",});}// 不管响应成功还是失败,收到后端响应的消息后就不再让登录按钮显示加载动画了_this.loading = false;console.log(res);});} else {  // 如果账号或密码有一个没填,就直接提示必填,不向后端请求console.log("error submit!!");this.loading = false;return false;}});},resetForm(formName) {this.$refs[formName].resetFields();},},
};
</script><style scoped>
/* 设置登录面板居中,宽度为400px */
.box-card {margin: auto auto;width: 400px;
}
/* 设置登录面板中的表单居中 */
.login-from {margin: auto auto;
}
</style>

src\views\home\Home.vue

<template><div><h2>欢迎{{ user.username }}!您的 uid 为{{ user.id }}</h2><el-button @click="logout"> 登出 </el-button></div>
</template><script>
export default {data() {return {user: {username: "",id: null,},};},methods: {logout(){// 移除本地用户登录信息sessionStorage.removeItem('userInfo');// 跳转页面到登录页this.$router.push('/login');}},mounted() {if (sessionStorage.getItem('userInfo')) {// 将用户信息存储到sessionStorage中this.user = JSON.parse(sessionStorage.getItem('userInfo'));}},
};
</script><style scoped>
</style>

src\router\index.js

// 此文件专门负责项目的路由import VueRouter from "vue-router"// 引入组件
import Login from '../views/login/Login'
import Register from '@/views/register/Register.vue'
import Home from '@/views/home/Home.vue'// 创建并暴露一个路由器
export default new VueRouter({mode: 'history',    // 路由模式,该模式不会在地址中显示井号#routes: [{path: '/',          // 路径redirect: '/login'  // 重定向},{path: '/login',     // 路径component: Login    // 跳转到的组件},{path: '/register',     // 路径component: Register    // 跳转到的组件},{path: '/home',     // 路径component: Home    // 跳转到的组件}]
})

修改一下登录界面

去掉注册功能

src\views\login\Login.vue

删除红色框部分

src\views\register

src\router\index.js

添加背景图片

src\views\login\Login.vue

测试

完整代码

src\views\login\Login.vue

<template><div class="login-background"><el-card class="box-card"><h2>体育器材管理后台</h2><el-form:model="ruleForm"status-icon:rules="rules"ref="ruleForm"label-position="left"label-width="70px"class="login-from"><el-form-item label="用户名" prop="username"><el-input v-model="ruleForm.username"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-inputtype="password"v-model="ruleForm.password"autocomplete="off"></el-input></el-form-item></el-form><div class="btnGroup"><el-buttontype="primary"@click="submitForm('ruleForm')"v-loading="loading">登录</el-button><el-button @click="resetForm('ruleForm')">重置</el-button></div></el-card></div>
</template><script>export default {data() {return {ruleForm: {username: "",password: "",},rules: {username: [{ required: true, message: "用户名不能为空!", trigger: "blur" },],password: [{ required: true, message: "密码不能为空!", trigger: "blur" },],},loading: false, // 是否显示加载动画};},methods: {submitForm(formName) {// 验证表单中的账号密码是否有效,因为在上面rules中定义为了必填 required: truethis.$refs[formName].validate((valid) => {// 点击登录后,让登录按钮开始转圈圈(展示加载动画)this.loading = true;// 如果经过校验,账号密码都不为空,则发送请求到后端登录接口if (valid) {let _this = this;// 使用 axios 将登录信息发送到后端this.axios({url: "/api/admin/student/login",               // 请求地址method: "post",                       // 请求方法headers: {                            // 请求头"Content-Type": "application/json",},data: {                             // 请求参数username: _this.ruleForm.username,password: _this.ruleForm.password,},}).then((res) => { // 当收到后端的响应时执行该括号内的代码,res 为响应信息,也就是后端返回的信息if (res.data.code === 1) {  // 当响应的编码为 1 时,说明登录成功// 将用户信息存储到sessionStorage中sessionStorage.setItem("userInfo", JSON.stringify(res.data.data));// 跳转页面到首页this.$router.push('/home');// 显示后端响应的成功信息this.$message({message: res.data.data,type: "success",});} else {  // 当响应的编码不为 1 时,说明登录失败// 显示后端响应的失败信息this.$message({message: res.data.msg,type: "warning",});}// 不管响应成功还是失败,收到后端响应的消息后就不再让登录按钮显示加载动画了_this.loading = false;console.log(res);});} else {  // 如果账号或密码有一个没填,就直接提示必填,不向后端请求console.log("error submit!!");this.loading = false;return false;}});},resetForm(formName) {this.$refs[formName].resetFields();},},
};
</script><style scoped>
/* 设置登录面板居中,宽度为400px */
.box-card {margin: auto auto;width: 400px;
}
/* 设置登录面板中的表单居中 */
.login-from {margin: auto auto;
}/* 背景图片 */
.login-background {  background-image: url('/src/assets/bg.jpeg');  background-size: cover;  background-position: center;  height: 100vh;  display: flex; /* 如果你想要使用Flexbox来居中el-card  */ justify-content: center; /* 水平居中 */  align-items: center; /* 垂直居中 */  
}  
</style>

相关文章:

开始尝试从0写一个项目--前端(一)

基础项目构建 创建VUE初始工程 确保自己下载了node.js和npm node -v //查看node.js的版本 npm -v //查看npm的版本 npm i vue/cli -g //安装VUE CLI 创建 以管理员身份运行 输入&#xff1a;vue ui 就会进入 点击创建 自定义项目名字&#xff0c;选择npm管理 结…...

【Java探索之旅】多态:向上下转型、多态优缺点、构造函数陷阱

文章目录 &#x1f4d1;前言一、向上转型和向下转型1.1 向上转型1.2 向下转型 二、多态的优缺点2.1 多态优点2.2 多态缺陷 三、避免避免构造方法中调用重写的方法四、好的习惯&#x1f324;️全篇总结 &#x1f4d1;前言 在面向对象编程中&#xff0c;向上转型和向下转型是常用…...

Linux上web服务器搭建(Apache、Nginx)

第五章 web服务器 第一节 DNS&#xff1a;对域名进行解析&#xff0c;查询对应的地址 1.1 web服务器简介 www是world wide web的缩写&#xff0c;也就是全球信息广播的意思 1.2.网址及HTTP简介 web服务器提供的这些数据大部分都是文件&#xff0c;那么我们需要在服务器端…...

Django QuerySet对象,exclude()方法

模型参考上一章内容&#xff1a; Django QuerySet对象&#xff0c;filter()方法-CSDN博客 exclude()方法&#xff0c;用于排除符合条件的数据。 1&#xff0c;添加视图函数 Test/app11/views.py from django.shortcuts import render from .models import Postdef index(re…...

Qt/C++音视频开发78-获取本地摄像头支持的分辨率/帧率/格式等信息/mjpeg/yuyv/h264

一、前言 上一篇文章讲到用ffmpeg命令方式执行打印到日志输出&#xff0c;可以拿到本地摄像头设备信息&#xff0c;顺藤摸瓜&#xff0c;发现可以通过执行 ffmpeg -f dshow -list_options true -i video“Webcam” 命令获取指定摄像头设备的分辨率帧率格式等信息&#xff0c;会…...

Go bufio包

bufio包&#xff1a; 带缓冲的I/O操作&#xff0c; 减少系统调用次数&#xff0c; 读取文件、网络数据。 bufio包 是什么 bufio 包是 Go 标准库中的一个非常有用的包&#xff0c;用于提供带缓冲的 I/O 操作。它通过缓冲来提高读取和写入的效率&#xff0c;可以有效减少系统调用…...

C++ 类和对象 拷贝构造函数

一 拷贝构造函数的概念&#xff1a; 拷贝构造函数是一种特殊的构造函数&#xff0c;用于创建一个对象是另一个对象的副本。当需要用一个已存在的对象来初始化一个新对象时&#xff0c;或者将对象传递给函数或从函数返回对象时&#xff0c;会调用拷贝构造函数。 二 拷贝构造函…...

C# —— Math对象

Math 数学类 提供了一些相关数学计算的属性和方法、四舍五入、向上求整、向下求整、开平方&#xff0c;几次方 最大值和最小值 sin cos 绝对值 方法 1.Math 常用的字段 Math.PI double x 2 * 180 / Math.PI; Console.WriteLine(x); 2 Math.Abs() 求绝对值 int a -3; Con…...

Face_recognition实现人脸识别

这里写自定义目录标题 欢迎使用Markdown编辑器一、安装人脸识别库face_recognition1.1 安装cmake1.2 安装dlib库1.3 安装face_recognition 二、3个常用的人脸识别案例2.1 识别并绘制人脸框2.2 提取并绘制人脸关键点2.3 人脸匹配及标注 欢迎使用Markdown编辑器 本文基于face_re…...

1-3分钟爆款视频素材在哪找啊?这9个热门爆款素材网站分享给你

在如今快节奏的时代&#xff0c;短视频已成为吸引观众注意力的黄金手段。然而&#xff0c;要制作出1-3分钟的爆款视频&#xff0c;除了创意和剪辑技巧外&#xff0c;选择合适的素材至关重要。那么&#xff0c;哪里可以找到那些能让你的视频脱颖而出的爆款素材呢&#xff1f;不用…...

武汉免费 【FPGA实战训练】 Vivado入门与设计师资课程

一&#xff0e;背景介绍 当今高度数字化和智能化的工业领域&#xff0c;对高效、灵活且可靠的技术解决方案的需求日益迫切。随着工业 4.0 时代的到来&#xff0c;工业生产过程正经历着前所未有的变革&#xff0c;从传统的机械化、自动化逐步迈向智能化和信息化。在这一背景下&…...

【vite创建项目】

搭建vue3tsvitepinia框架 一、安装vite并创建项目1、用vite构建项目2、配置vite3、找不到模块 “path“ 或其相对应的类型声明。 二、安装element-plus1、安装element-plus2、引入框架 三、安装sass sass-loader1、安装sass 四、安装vue-router-next 路由1、安装vue-router42搭…...

最优化方法 运筹学【】

1.无约束 常用公式 线搜索准则&#xff1a;求步长 精确线搜索&#xff08;argmin&#xff09; 最速下降&#xff1a;sd&#xff1a;线性收敛 2.算法 SD dk&#xff1a;付梯度-g newton dk&#xff1a;Gkd-g 二阶收敛&#xff0c;步长为1 阻尼牛顿&#xff1a;步长用先搜…...

探索 WebKit 的动感世界:设备方向和运动支持全解析

探索 WebKit 的动感世界&#xff1a;设备方向和运动支持全解析 随着移动设备的普及&#xff0c;网页应用对设备方向和运动的感知需求日益增长。WebKit 作为众多流行移动浏览器的渲染引擎&#xff0c;提供了对设备方向和运动的全面支持&#xff0c;使得 Web 应用能够根据设备的…...

高考假期预习指南

IT专业入门&#xff0c;高考假期预习指南 对于希望进入IT行业的学生来说&#xff0c;假期是学习信息技术的最佳时机。 在信息化快速发展的时代&#xff0c;IT行业的发展前景广阔&#xff0c;但高技能要求使新生可能感到迷茫。 建议新生制定详细的学习计划&#xff0c;包括了解…...

Spring Boot 事件监听机制工作原理

前言&#xff1a; 我们知道在 Spring 、Spring Boot 的启动源码中都大量的使用了事件监听机制&#xff0c;也就是我们说的的监听器&#xff0c;监听器的实现基于观察者模式&#xff0c;也就是我们所说的发布订阅模式&#xff0c;这种模式可以在一定程度上实现代码的解耦&#…...

【AI大模型】驱动的未来:穿戴设备如何革新血液、皮肤检测与营养健康管理

文章目录 1. 引言2. 现状与挑战3. AI大模型与穿戴设备概述4. 数据采集与预处理4.1 数据集成与增强4.2 数据清洗与异常检测 5. 模型架构与训练5.1 高级模型架构5.2 模型训练与调优 6. 个性化营养建议系统6.1 营养建议生成优化6.2 用户反馈与系统优化 7. 关键血液成分与健康状况评…...

【FFmpeg】avcodec_open2函数

目录 1. avcodec_open21.1 编解码器的预初始化&#xff08;ff_encode_preinit & ff_decode_preinit&#xff09;1.2 编解码器的初始化&#xff08;init&#xff09;1.3 释放编解码器&#xff08;ff_codec_close&#xff09; FFmpeg相关记录&#xff1a; 示例工程&#xff…...

matlab:对带参数a关于x的方程求解

题目 讲解 简洁对各个式子的内部含义用浅显易懂的话语总结出来了&#xff0c;耐心体会 f(a) (x)exp(x)x^ax^(sqrt(x))-100;%因为下面的fzero的第一个数需要一个fun&#xff0c;所以这里有两个句柄&#xff0c;第一个a是输入的&#xff0c;第二个x是需要被解出的 A0:0.1:2;%创…...

Yolov10训练,转化onnx,推理

yolov10对于大目标的效果好&#xff0c;小目标不好 一、如果你训练过yolov5&#xff0c;yolov8&#xff0c;的话那么你可以直接用之前的环境就行 目录 一、如果你训练过yolov5&#xff0c;yolov8&#xff0c;的话那么你可以直接用之前的环境就行 二、配置好后就可以配置文件…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...