前面分别讲了 Python(Falsk) 、 React 、 Golang(Gin) 、 Vue(Element),现在整体的给大家汇报一下,这个是简单搭建的demo,后面的添砖加瓦需要自己动手咯,有不明白的可以参考一下小编前面的文章,也许会给大家有答疑解惑的帮助
Python(Falsk):
https://blog.csdn.net/masterphp/article/details/136290855
https://blog.csdn.net/masterphp/article/details/138627802
React:
https://blog.csdn.net/masterphp/article/details/139242705
Golang(Gin):
https://blog.csdn.net/masterphp/article/details/129757434
https://blog.csdn.net/masterphp/article/details/130877001
https://blog.csdn.net/masterphp/article/details/131493155
https://blog.csdn.net/masterphp/article/details/131523360
https://blog.csdn.net/masterphp/article/details/132208407
https://blog.csdn.net/masterphp/article/details/132307220
https://blog.csdn.net/masterphp/article/details/132414796
Vscode的安装:
首先讲一下Vscode的安装(用于React和Vue),本次完成项目的搭建,借助了一个工具:通意灵码,通意灵码:基于阿里云提供的一个服务,说的明白一点就是一个智能代码辅助工具,实际上用下来,个人觉得和Chatgpt平分秋色,各有各的优点与弊端,所以建议大家两个都去安装一下,适合自己的才是最好的
node14版本以上安装:
1.安装13版本
2.下载14版本zip(覆盖安装目录)
3.设置环境变量:NODE_SKIP_PLATFORM_CHECK :1
4.命令行使用 node -v 指令和npm -v ,检查当前 node 版本是否更新成功
5.设置全局模块存放路径和缓存文件夹(新建:node_global文件夹 + node_cache文件夹)
6.npm config set prefix "E:\node\node_global" npm config set cache "E:\node\node_cache"
7.更换淘宝镜像(npm config set registry=https://registry.npm.taobao.org)
8.查看配置是否成功(npm config list)
9.设置环境变量: C:\Users\你的用户名\AppData\Roaming\npm 修改为 你的安装目录\node_global
10.新建环境变量(NODE_PATH :你的安装目录\node_global\node_modules)
11.新建环境变量(Path:%NODE_PATH%)
npm命令:
react-router-dom 安装命名(路由包):
npm install react-router-dom
antdesign安装命令(前端UI):
npm install antd --save
npm add antd@^4.24.2
使antdesign用babel-plugin-import插件可以实现按需加载:
npm install babel-plugin-import --save-dev
查看typescript版本:
npm view typescript version
CSS样式(5.0版本以下)
import 'antd/dist/antd.min.css'
CSS样式(5.0版本以上)
import 'antd/dist/antd.css'
cnpm安装
安装命令: npm install -g cnpm --registry=https://registry.npm.taobao.org 命令行下输入: cnpm -v 验证是否安装成功。
npm升级命令
npm install -g tar
npm uninstall fstream
安装react:
1.npm install -g create-react-app(或者 npx create-react-app my-app)
2.create-react-app my-app(其中my-app是你的项目名称)
3.进入创建的项目目录:cd my-app
4.启动开发服务器:npm start
切换镜像:
npm config set registry= https://registry.npmjs.org/
npm config set registry=https://registry.npm.taobao.org
Python使用的工具的PaCharm,使用这个工具的话需要激活码,所以大家懂的,有工具的,另外来说前期一个月的时间建议大家关闭代码提示,后期可以开启,主要是前期关闭可以加强关联记忆
Golang使用的工具是Goland,其实使用Vscode也是非常好用的,看个人习惯,当然这个也是需要激活码的,所以嫌麻烦的同学可以直接上Vscode
Golang(Gin) + Vue:项目结构
GIN框架主入口:
package main
import (
//GIN框架引入
"github.com/gin-gonic/gin"
//自定义模块引入
"project/common"
user "project/controller"
)
//初始化
func init() {
//数据库初始化
common.Dbinit()
}
func main() {
//GIN框架初始化
r := gin.Default()
//设置安全访问
r.SetTrustedProxies([]string{"127.0.0.1"})
//定义常量
r.Static("/source", "static")
//设置模版
r.LoadHTMLGlob("template/*")
/*******************登录页开始***********************/
r.GET("/login", func(c *gin.Context) {
c.HTML(200,"login.html", gin.H{"title": "登录"})
})
r.POST("/logindo", func(context *gin.Context) {
username := context.PostForm("username")
password := context.PostForm("password")
//判断
if(username == "12" && password == "34"){
//todo 设置session
//返回值
context.JSON(200, gin.H{
"code": 0,
"message":"成功",
})
}else{
context.JSON(200, gin.H{
"code": 1,
"message":"参数错误",
})
}
})
/*******************登录页结束***********************/
/*******************首页开始***********************/
r.GET("/index", func(context *gin.Context) {
context.HTML(200,"index.html",gin.H{"title": "首页"})
})
r.GET("/indexlist",user.Userlist)
/*******************首页结束***********************/
/*******************用户开始***********************/
r.GET("/user_add", func(context *gin.Context) {
context.HTML(200,"user_add.html",gin.H{"title":"新增用户"})
})
r.POST("/user_add_do",user.User_add_do)
//用户编辑
r.GET("/user_edit", func(context *gin.Context) {
id := context.Query("id")
context.HTML(200,"user_edit.html",gin.H{"title":"编辑用户","id":id})
})
r.POST("/user_info",user.User_info)
//操作编辑
r.POST("/user_edit_do",user.User_edit_do)
r.POST("/user_del", user.User_del)
/*******************用户结束***********************/
/*******************文件上传开始***********************/
r.POST("/imgupload",common.Imgupload)
/*******************文件上传结束***********************/
r.Run("localhost:8080")
}
数据库初始化:
package common
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
//定义全局变量
var DB *gorm.DB
// 连接数据库的函数,返回一个 *sql.DB 对象以及一个 error 对象 (方法名记得大写,才可以被外部引用)。
func Dbinit(){
dsn := "root:root@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
DB,_ = gorm.Open(mysql.Open(dsn), &gorm.Config{})
fmt.Print("connect success")
}
公共方法:
package common
import (
"github.com/gin-gonic/gin"
)
// 定义一个结构体来映射分页查询的数据
type Pagination struct {
// 当前页码
Page int `json:"page"`
// 每页数量
PageSize int `json:"pageSize"`
// 总页数
TotalPages int `json:"totalPages"`
// 总记录数
TotalCount int `json:"totalCount"`
}
// 定义一个结构体来映射返回的数据
type Response struct {
// 状态码
Code int `json:"code"`
// 数据
Data interface{} `json:"data"`
// 消息
Msg string `json:"msg"`
}
type Publicmodel struct {
ID uint `json:"id" gorm:"primaryKey"`
}
//文件上传
func Imgupload(context *gin.Context) {
// 单个文件(判断上传的文件是否为空)
file, err := context.FormFile("file")
if err != nil {
context.JSON(500, gin.H{
"message": err.Error(),
})
return
}
//文件上传路径
dst := "./static/img/upload/" + file.Filename
// 上传文件到指定的目录
context.SaveUploadedFile(file, dst)
//返回数据
context.JSON(200, gin.H{
"message": "上传成功",
"filename": file.Filename,
"raw": dst,
})
}
登录页面:
<style>
@import url("/source/index.css");
.el-input__inner{width: 80%!important;}
#app{width: 100%;height: 100%;background: url(/source/img/loginbg.png) #F5F5F5 no-repeat;background-size: 70%;position: absolute}
#content{ box-shadow: 22px 22px 0px #ebebeb;margin-top: 10%;z-index: 999;width: 475px;padding: 2rem;
box-sizing: border-box;background-color: #fff;border-radius: 5px;position: relative;left: 60%;height: 30%}
</style>
<script src="/source/vue.js"></script>
<script src="/source/index.js"></script>
<script src="/source/axios.min.js"></script>
<div id="app">
<div id="content">
<el-form ref="form" :model="form" label-width="80px" >
<el-form-item label="账号">
<el-input type="text" v-model="form.username" autocomplete="off" placeholder="请输入账号"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input type="password" v-model="form.password" autocomplete="off" maxlength="10" placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit(form)">立即创建</el-button>
</el-form-item>
</el-form>
</div>
</div>
<script>
var Main = {
data() {
return {
form: {
username: '',
password: '',
},
defaultProps: {
children: 'children',
label: 'label'
}
}
},
methods: {
onSubmit(form) {
//必须使用这个数组
// let param = new URLSearchParams()
let param = new FormData()
//填充护数据
param.append('username',this.form.username)
param.append('password',this.form.password)
//异步请求数据
axios.post("/logindo",param)
.then((response)=>{
if(response.data.code == 0){
this.$message("提示:"+response.data.message);
location.replace("/index", "_self");
}else{
this.$message("提示:"+response.data.message);
}
})
.catch((error)=>{//错误捕获
this.$message("请求错误,请重试");
});
},
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
</script>
列表页面:
<style>
@import url("/source/index.css");
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
<script src="/source/vue.js"></script>
<script src="/source/index.js"></script>
<script src="/source/axios.min.js"></script>
<div id="app">
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu :default-openeds="['1', '3']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>导航一</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<!--右上角菜单开始-->
<el-header style="text-align: right; font-size: 12px">
<el-dropdown>
<i class="el-icon-setting" style="margin-right: 15px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>查看</el-dropdown-item>
<el-dropdown-item>新增</el-dropdown-item>
<el-dropdown-item>删除</el-dropdown-item>
<el-dropdown-item></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span>王小虎</span>
<el-button type="primary" @click="login_out()">退出</el-button>
</el-header>
<!--右上角菜单结束-->
<!--主体开始-->
<el-main>
<el-row>
<el-input v-model="input" placeholder="请输入内容" style="width: 80%"></el-input>
<el-button type="primary">搜索</el-button>
<el-button type="primary" @click="user_add()">新增</el-button>
</el-row>
<el-table :data="tableData">
<el-table-column prop="id" label="ID" width="140">
</el-table-column>
<el-table-column prop="username" label="姓名" width="120">
</el-table-column>
<el-table-column prop="sex" label="性别">
</el-table-column>
<el-table-column prop="age" label="年龄">
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
size="mini"
@click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[1, 2, 3, 4,5,6,7,8,9,10]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</el-main>
<!--主体结束-->
</el-container>
</el-container>
</div>
<script>
var Main = {
data() {
return {
tableData: [],
currentPage: 1,
pageSize: 2,
total: 0,
input: '',
};
},
methods: {
//定义刷新方法
fetchData(page, size) {
// 这里的API请求应该替换为实际的API地址和参数
axios.get('/indexlist', {
params: {
page: page,
size: size
}
}).then(response => {
this.tableData = response.data.data.users;
this.total = response.data.data.pagination.totalCount;
}).catch(error => {
console.error('Error fetching data: ', error);
});
},
handleSizeChange(val) {
this.pageSize = val;
this.fetchData(this.currentPage, this.pageSize);
},
handleCurrentChange(val) {
this.currentPage = val;
this.fetchData(this.currentPage, this.pageSize);
},
handleEdit(index, row) {//编辑
var id = row.id
var url = "/user_edit?id="+id;
location.replace(url, "_self");
},
handleDelete(index, row) {//删除
//异步请求
axios({
method: "post",
url: "/user_del",
data: {id:row.id},
headers: { "Content-Type": "multipart/form-data" },
}).then((response) => {
if(response.data.code ==200){
this.$message("提示:"+response.data.msg);
//跳转
this.fetchData(this.currentPage, this.pageSize);
}else{
this.$message("提示:"+response.data.msg);
}
});
},
//退出
login_out(){
this.$message("退出提示");
},
//用户新增
user_add(){
var url = "/user_add";
location.replace(url, "_self");
}
},
mounted(){//初始化加载
this.fetchData(this.currentPage, this.pageSize);
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
</script>
添加数据:
<style>
@import url("/source/index.css");
#content{width: 100%;height: 100%}
</style>
<script src="/source/vue.js"></script>
<script src="/source/index.js"></script>
<script src="/source/axios.min.js"></script>
<div id="app">
<div id="content">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="真实名称">
<el-input v-model="form.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="性别">
<el-select v-model="form.sex" placeholder="请选择性别">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</el-form-item>
<el-form-item label="年龄">
<el-input type="number" v-model="form.age" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</div>
</div>
<script>
var Main = {
data() {
return {
form: {
username: '',
sex: '',
age: '',
}
}
},
methods: {
onSubmit(form) {
//必须使用这个数组
// let param = new URLSearchParams()
let param = new FormData()
//填充护数据
param.append('username',this.form.username)
param.append('sex',this.form.sex)
param.append('age',this.form.age)
//异步请求数据
axios.post("/user_add_do",param)
.then((response)=>{
if(response.data.code ==200){
this.$message("提示:"+response.data.msg);
//跳转
setTimeout(function () {
var url = "/index";
location.replace(url, "_self");
},1000);
}else{
this.$message("提示:"+response.data.msg);
}
})
.catch((error)=>{//错误捕获
this.$message("请求错误,请重试");
});
},
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
</script>
编辑数据:
<style>
@import url("/source/index.css");
#content{width: 100%;height: 100%}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
<script src="/source/vue.js"></script>
<script src="/source/index.js"></script>
<script src="/source/axios.min.js"></script>
<div id="app">
<div id="content">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="用户ID">
<el-input type="number" v-model="form.id" autocomplete="off" disabled></el-input>
</el-form-item>
<el-form-item label="真实名称">
<el-input v-model="form.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="性别">
<el-select v-model="form.sex" placeholder="请选择性别">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</el-form-item>
<el-form-item label="年龄">
<el-input type="number" v-model="form.age" autocomplete="off"></el-input>
</el-form-item>
<!--图片上传开始-->
<el-form-item label="头像" v-model="form.url">
<el-upload
class="avatar-uploader"
action="/imgupload"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
<!--图片上传结束-->
<el-form-item>
<el-button type="primary" @click="onSubmit">确认修改</el-button>
</el-form-item>
</el-form>
</div>
</div>
<script>
var Main = {
data() {
return {
form: {
id: '{{.id}}',
username: '',
sex: '',
age: '',
},
imageUrl: ''
}
},
methods: {
fetchData() {
// 这里的API请求应该替换为实际的API地址和参数
axios({
method: "post",
url: "/user_info",
data: {id:'{{.id}}'},
headers: { "Content-Type": "multipart/form-data" },
}).then((response) => {
if(response.data.code ==200){
//数据填充
this.form.username = response.data.data.users[0].username;
this.form.sex = response.data.data.users[0].sex;
this.form.age = response.data.data.users[0].age;
this.imageUrl = response.data.data.users[0].url;
}else{
this.$message("提示:"+response.data.msg);
}
});
},
onSubmit(form) {
//填充数据
let param = new FormData()
//填充护数据
param.append('id',this.form.id)
param.append('username',this.form.username)
param.append('sex',this.form.sex)
param.append('age',this.form.age)
param.append('url',this.imageUrl)
//异步请求数据
axios.post("/user_edit_do",param)
.then((response)=>{
if(response.data.code ==200){
this.$message("提示:"+response.data.msg);
//跳转
setTimeout(function () {
var url = "/index";
location.replace(url, "_self");
},1000);
}else{
this.$message("提示:"+response.data.msg);
}
})
.catch((error)=>{//错误捕获
this.$message("请求错误,请重试");
});
},
handleAvatarSuccess(res, file) {
this.imageUrl = file.response.raw.replace("./static","http://127.0.0.1:8080/source")
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
},
},
mounted(){//初始化加载
this.fetchData();
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
</script>
Python(Falsk) + React 项目结构
Python(Flask)框架主入口:
from flask import Flask,Blueprint,json
from flask_cors import CORS
from xst.controller.user_controller import *
from xst.mapper.fileupload import *
import requests
from bs4 import BeautifulSoup
app = Flask(__name__)
#设置跨域
CORS(app)
# 蓝图
admin = Blueprint('admin', __name__)
# 登录操作
@admin.route('/logindo',methods=['POST'])
def logindo():
# 获取数据(方式一)
username = request.form['username']
# 获取数据(方式二)
# data = request.form.to_dict()
# username = request.form['username']
# 数据操作
logindata = Userlogin(username)
return json.dumps(logindata)
# 用户列表
@admin.route('/userlist',methods=['POST','GET'])
def userlist():
list = Userlist()
return json.dumps(list)
# 用户个数
@admin.route('/usernum',methods=['POST','GET'])
def usernum():
num = Usercount()
return json.dumps(num)
# 用户新增
@admin.route("/useradd",methods=["POST"])
def useradd():
# 接收数据
username = request.form['username']
sex = request.form['sex']
age = request.form['age']
url = request.form['url']
# 请求方法
result = Useradd(username,sex,age,url)
return json.dumps(result)
# 用户修改
@admin.route("/useredit",methods=["POST"])
def useredit():
# 请求方法
return json.dumps(Useredit())
# 文件上传
@admin.route("/fileupload",methods=["POST"])
def fileupload():
return json.dumps(Fileupload())
# 蓝图注册
app.register_blueprint(admin,url_prefix='/admin')
if __name__ == '__main__':
app.run()
公共方法:
from flask import Flask
import mysql.connector
# 数据库连接(设置参数)
mydb = mysql.connector.connect(
host="localhost",
user="root",
passwd="root",
database="test"
)
from flask import request
from werkzeug.utils import secure_filename
import os
# 指定文件上传路径
UPLOAD_PATH = "/upload"
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
# 数据过滤器
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
# 文件上传方法
def Fileupload():
# 判断文件是否存在
if 'file' not in request.files:
data = {
"code": "300",
"msg": "修改成功",
"data": ""
}
return data
# 获取文件
file = request.files['file']
if file.filename == '':
data = {
"code": "300",
"msg": "未选择文件",
"data": ""
}
return data
# 这里可以加入文件类型的判断
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(UPLOAD_PATH, filename))
data = {
"code": "200",
"msg": "上传成功",
"data": filename
}
return data
数据处理:
from xst.mapper.exts import mydb
from flask import request
# 用户登录
def Userlogin(usernum):
mycursor = mydb.cursor()
# 获取数据量
mycursor.execute("SELECT count(users.id) as num FROM users where username = '" + usernum + "'")
num = mycursor.fetchone()[0]
# 获取数据
mycursor.execute("SELECT * FROM users where username = '" + usernum + "'")
userinfo = mycursor.fetchall()
# 判断
if num >0:
data = {
"code": "200",
"msg": "成功",
"data": userinfo
}
else:
data = {
"code": "300",
"msg": "失败",
"data": ""
}
# 返回
return data
# 数据查询(获取数据量)
def Usercount():
mycursor = mydb.cursor()
mycursor.execute("SELECT count(users.id) as num FROM users")
num = mycursor.fetchone()[0]
# 数据组合
data = {
"code": "200",
"msg": "成功",
"data": num
}
# 返回
return data
# 数据查询(全部数据)
def Userlist():
mycursor = mydb.cursor()
mycursor.execute("SELECT * FROM users")
userlist = mycursor.fetchall()
# 数据组合
data = {
"code": "200",
"msg": "成功",
"data": userlist
}
# 返回
return data
# 数据查询(新增用户)
def Useradd(username,sex,age,url):
mycursor = mydb.cursor()
mycursor.execute("INSERT INTO users (username, sex, age, url) VALUES ('"+username+"', '"+sex+"', "+age+", '"+url+"');")
mydb.commit()
new_id = mycursor.lastrowid
# 判断
if new_id >0:
data = {
"code": "200",
"msg": "新增成功",
"data": new_id
}
else:
data = {
"code": "300",
"msg": "新增失败",
"data": ""
}
# 返回
return data
# 数据查询(修改用户)
def Useredit():
# //接收数据
id = request.form['id']
username = request.form['username']
sex = request.form['sex']
age = request.form['age']
url = request.form['url']
# 数据操作
mycursor = mydb.cursor()
mycursor.execute("UPDATE users SET username = '"+username+"', sex = '"+sex+"', age = "+age+", url = '"+url+"' WHERE id = "+id)
mydb.commit()
# 判断
if mycursor.rowcount > 0:
data = {
"code": "200",
"msg": "修改成功",
"data": ""
}
else:
data = {
"code": "300",
"msg": "修改失败",
"data": ""
}
# 返回
return data
React主入口文件:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import Route from './pages/route';
import reportWebVitals from './reportWebVitals';
// 新增路由组件
import { BrowserRouter } from "react-router-dom"
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<Route />
</BrowserRouter>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
主文件:
import React from "react";
import { useRoutes } from "react-router-dom"
import Userlist from "./userlist";
import Useradd from "./useradd";
import Useredit from "./useredit";
import Layout from "./layout";
function Route(){
const routes = useRoutes([
{ path: "/userlist", element: <Userlist /> },
{ path: "/useradd", element: <Useradd /> },
{ path: "/useredit", element: <Useredit /> },
{ path: "/*", element: <Layout /> },
]);
return (
<div className="container">
<div className="layout">
<div style={{ width: '100%' }}>
{routes}
</div>
</div>
</div>
);
}
export default Route;
数据列表:
import React from 'react';
import { LikeOutlined, MessageOutlined, StarOutlined } from '@ant-design/icons';
import {List, Space } from 'antd';
function Userlist(){
// 设置数据
const data = Array.from({ length: 23 }).map((_, i) => ({
// 跳转地址
href: 'https://ant.design',
title: `序号: ${i}`,
description:
'描述',
content:
'内容',
}));
//列表渲染
return (
<List
itemLayout="vertical"
size="large"
pagination={{
onChange: page => {
console.log(page);
},
pageSize: 3,
}}
dataSource={data}
renderItem={item => (
<List.Item
key={item.title}
extra={
<img
width={272}
alt="logo"
src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png"
/>
}
>
<List.Item.Meta
title={<a href={item.href}>{item.title}</a>}
description={item.description}
/>
{item.content}
</List.Item>
)}
/>
);
}
export default Userlist;
新增数据:
import React from 'react';
// antdesign引入
import { Button, Form, Input,InputNumber } from 'antd';
import { InboxOutlined } from '@ant-design/icons';
import { message, Upload,Select } from 'antd';
import "./layout.css"
// 方法定义
function Useradd(){
//常量定义
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
//上传组件初始化
const { Dragger } = Upload;
const props = {
name: 'file',
multiple: true,
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
onChange(info) {
const { status } = info.file;
if (status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (status === 'done') {
message.success(`${info.file.name} file uploaded successfully.`);
} else if (status === 'error') {
message.error(`${info.file.name} file upload failed.`);
}
},
onDrop(e) {
console.log('Dropped files', e.dataTransfer.files);
},
};
//定义下拉组件
const { Option } = Select;
// 方法定义
return (
<Form
name="basic"
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
initialValues={{
remember: true,
}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
{/* 用户名 */}
<Form.Item
label="用户名"
name="username"
rules={[
{
required: true,
message: 'Please input your 用户名!',
},
]}
>
<Input />
</Form.Item>
{/* 性别 */}
<Form.Item
label="性别"
name="sex"
rules={[
{
required: true,
message: 'Please input your 性别!',
},
]}
>
<Select
placeholder="选择性别"
allowClear
>
<Option value="男">男</Option>
<Option value="女">女</Option>
</Select>
</Form.Item>
{/* 年龄 */}
<Form.Item name={['user', 'age']} label="年龄" rules={[{ type: 'number', min: 0, max: 99 }]}>
<InputNumber />
</Form.Item>
{/* 头像 */}
<Form.Item label="头像"name="url">
<Dragger {...props} maxCount={1}>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">点击上传</p>
<p className="ant-upload-hint">支持单次或批量上传</p>
</Dragger>
</Form.Item>
<Form.Item
wrapperCol={{
offset: 8,
span: 16,
}}
>
<Button type="primary" htmlType="submit">提交</Button>
</Form.Item>
</Form>
);
}
export default Useradd;
编辑数据:
import React from 'react';
// antdesign引入
import { Button, Form, Input,InputNumber } from 'antd';
import { InboxOutlined } from '@ant-design/icons';
import { message, Upload,Select } from 'antd';
import "./layout.css"
// 方法定义
function Useradd(){
//常量定义
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
//上传组件初始化
const { Dragger } = Upload;
const props = {
name: 'file',
multiple: true,
action: 'http://127.0.0.1:500/fileupload',
onChange(info) {
const { status } = info.file;
if (status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (status === 'done') {
message.success(`${info.file.name} file uploaded successfully.`);
} else if (status === 'error') {
message.error(`${info.file.name} file upload failed.`);
}
},
onDrop(e) {
console.log('Dropped files', e.dataTransfer.files);
},
};
//定义下拉组件
const { Option } = Select;
// 方法定义
return (
<Form
name="basic"
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
initialValues={{
remember: true,
}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
{/* 用户名 */}
<Form.Item
label="用户名"
name="username"
rules={[
{
required: true,
message: 'Please input your 用户名!',
},
]}
>
<Input />
</Form.Item>
{/* 性别 */}
<Form.Item
label="性别"
name="sex"
rules={[
{
required: true,
message: 'Please input your 性别!',
},
]}
>
<Select
placeholder="选择性别"
allowClear
>
<Option value="男">男</Option>
<Option value="女">女</Option>
</Select>
</Form.Item>
{/* 年龄 */}
<Form.Item name={['user', 'age']} label="年龄" rules={[{ type: 'number', min: 0, max: 99 }]}>
<InputNumber />
</Form.Item>
{/* 头像 */}
<Form.Item label="头像"name="url">
<Dragger {...props} maxCount={1}>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">点击上传</p>
<p className="ant-upload-hint">支持单次或批量上传</p>
</Dragger>
</Form.Item>
<Form.Item
wrapperCol={{
offset: 8,
span: 16,
}}
>
<Button type="primary" htmlType="submit">修改</Button>
</Form.Item>
</Form>
);
}
export default Useradd;
公共样式:
.formbody{width: 40%;height: 25%;background: white;position: absolute;top: 30%;left: 50%;padding: 1.5rem !important;}
.ant-col-8{flex: 0 0 20% !important}
#root{padding: 1rem;}
至此讲解完成,主要讲解了登录、数据列表、数据新增、数据编辑,至于会话控制前面小编写的文章里面有,所以大家可以参考一下,还是那句话,脑袋会了手不一定会了,所以多练练习。