ASP.NET Core列表增删改查

前置要求:

1、 vue+element-plus实现前端静态页面

HelloWorld.vue(src->view)

<template><h2>hello界面</h2><div class="tableList"><!-- 搜索框 --><el-row :gutter="20"><el-col :span="8"><!-- 搜索与添加区域 --><el-input placeholder="请输入内容"v-model="SearchVal" clearable @clear="getUserList" @keyup.enter="enterSearch"><template #append><el-button @click="getUserList"><el-icon><search /></el-icon></el-button></template></el-input></el-col><el-col :span="2"><el-button type="primary" @click="openAdd">add</el-button></el-col><el-col :span="4"><el-button type="danger" @click="onDel">delete</el-button></el-col></el-row><!-- 表单 --><el-table :data="tableData" style="width: 100%"><el-table-column type="selection" width="55" /><el-table-column prop="date" label="Date" width="180" /><el-table-column prop="name" label="Name" width="100" /><el-table-column prop="oder" label="Oder" width="100" /><el-table-column prop="address" label="Address" /><!-- 操作按钮 --><el-table-column label="Operations"><template #default="scope"><el-button size="small" @click="handleEdit(scope.$index, scope.row)">Edit</el-button><el-buttonsize="small"type="danger"@click="handleDelete(scope.$index, scope.row)">Delete</el-button></template></el-table-column></el-table><el-pagination background layout="prev, pager, next" :total="total"  @current-change="handleCurrentChange"/></div>
</template><script lang="ts" setup >
import { ref } from "vue";
const SearchVal=ref("")
const total=ref(100)
const enterSearch=()=>{}
const openAdd=()=>{}
const onDel=()=>{}const handleEdit = (index: number, row: User) => {console.log(index, row)
}
const handleDelete = (index: number, row: User) => {console.log(index, row)
}const handleCurrentChange = (val: number) => {console.log(val)
}const tableData = [{date: '2016-05-03',name: 'Tom',oder:1,address: 'No. 189, Grove St, Los Angeles',},{date: '2016-05-02',name: 'Tom',oder:2,address: 'No. 189, Grove St, Los Angeles',},{date: '2016-05-04',name: 'Tom',oder:3,address: 'No. 189, Grove St, Los Angeles',},{date: '2016-05-01',name: 'Tom',oder:4,address: 'No. 189, Grove St, Los Angeles',},
]
</script><style lang="scss" scoped >
.tableList{margin:  0 500px;
}
.el-pagination{margin-top: 20px;
}
</style>

1.2 创建弹框组件app.vue(src->components)

<!-- 弹窗组件 -->
<template><el-dialog v-model="dialogFormVisible" title="新增" with="30%"><el-form :model="form"><el-form-item label="时间" prop="date"><el-input v-model="form.data" type="date" placeholder="请选择一个时间" :disabledDate="disabledDate"/></el-form-item><el-form-item label="名称" prop="name"><el-input v-model="form.name"></el-input></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="form.address"/></el-form-item><el-form-item label="排序" prop="order"><el-input v-model="form.oder"/></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button @click="dialogFormVisible = false">Cancel</el-button><el-button type="primary" @click="dialogFormVisible = false">Confirm</el-button></span></template></el-dialog>
</template>
<script setup lang="ts">
import {ref} from "vue"const dialogFormVisible=ref(false)
const form=ref()
const disabledDate=(time:any)=>{//最大时间从今天开始const _maxTime=Date.now()-24*60*60*1000*1return time.getTime()<=_maxTime
}</script><style scoped lang="scss">
.dialog-footer button:first-child {margin-right: 10px;
}
.el-button--text {margin-right: 15px;
}
.el-select {width: 300px;
}
.el-input {width: 300px;
}
.dialog-footer button:first-child {margin-right: 10px;
}
</style>

完善方法组件的代码:组件的引用,组件的传值prop,计算属性,事件监听、子触发父组件的事件

HelloWorld.vue

<template><h2>hello界面</h2><div class="tableList"><!-- 搜索框 --><el-row :gutter="20"><el-col :span="8"><!-- 搜索与添加区域 --><el-input placeholder="请输入内容"v-model="SearchVal" clearable @clear="getUserList" @keyup.enter="enterSearch"><template #append><el-button @click="getUserList"><el-icon><search /></el-icon></el-button></template></el-input></el-col><el-col :span="2"><el-button type="primary" @click="openAdd">add</el-button></el-col><el-col :span="4"><el-button type="danger" @click="onDel">delete</el-button></el-col></el-row><!-- 表单 --><el-table :data="tableData" style="width: 100%"><el-table-column type="selection" width="55" /><el-table-column prop="date" label="Date" width="180" /><el-table-column prop="name" label="Name" width="100" /><el-table-column prop="order" label="Order" width="100" /><el-table-column prop="address" label="Address" /><!-- 操作按钮 --><el-table-column label="Operations"><template #default="scope"><el-button size="small" @click="handleEdit(scope.$index, scope.row)">Edit</el-button><el-buttonsize="small"type="danger"@click="handleDelete(scope.$index, scope.row)">Delete</el-button></template></el-table-column></el-table><el-pagination background layout="prev, pager, next" :total="total"  @current-change="handleCurrentChange"/></div><addVue :isShow="isShow" :info="info" @closeAdd="closeAdd" @success="success"></addVue>
</template><script lang="ts" setup >
import { ref } from "vue";
import User from "../class/User.ts"
import addVue from "../components/add.vue"
import { ElMessage } from 'element-plus'
const SearchVal=ref("")
const total=ref(100)const isShow=ref(false)
//定义info
const info=ref<User>(new User())const enterSearch=()=>{}
const openAdd=()=>{isShow.value=true
}
const onDel=()=>{}const handleEdit = (index: number, row: User) => {console.log(index, row)info.value=rowisShow.value=true
}
const handleDelete = (index: number, row: User) => {console.log(index, row)
}const handleCurrentChange = (val: number) => {console.log(val)
}
const closeAdd=()=>{isShow.value=falseinfo.value=new User()
}
const success=()=>{isShow.value=falseinfo.value=new User()EIMessage.success(message)
}const tableData = [{date: '2016-05-03',name: 'Tom',order:1,address: 'No. 189, Grove St, Los Angeles',},{date: '2016-05-02',name: 'Tom',order:2,address: 'No. 189, Grove St, Los Angeles',},{date: '2016-05-04',name: 'Tom',order:3,address: 'No. 189, Grove St, Los Angeles',},{date: '2016-05-01',name: 'Tom',order:4,address: 'No. 189, Grove St, Los Angeles',},
]
</script><style lang="scss" scoped >
.tableList{margin:  0 500px;
}
.el-pagination{margin-top: 20px;
}
</style>

app.vue

作用:利用三元表达式,使用同一个组件展示不同的弹框内容

<!-- 弹窗组件 -->
<template><el-dialog v-model="dialogFormVisible" :title="info?.name?'修改':'新增'" with="30%" @close="$emit('closeAdd')" draggable="true"><!-- 使用三元表达式控制标题展示 --><el-form :model="form"><el-form-item label="时间" prop="date"><el-input v-model="form.date" type="date" placeholder="请选择一个时间" :disabledDate="disabledDate"/></el-form-item><el-form-item label="名称" prop="name"><el-input v-model="form.name"></el-input></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="form.address"/></el-form-item><el-form-item label="排序" prop="order"><el-input v-model="form.order"/></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button @click="closeAdd()">取消</el-button><el-button type="primary" @click="save()">确认</el-button></span></template></el-dialog>
</template>
<script setup lang="ts">
import {ref,Ref,computed,watch} from "vue"
import User from "../class/User"
const prop=defineProps({//内置的传参工具  接收使用prop传递过来的数据isShow:Boolean,//对于接收的类型进行控制info:User
})const disabledDate=(time:any)=>{//最大时间从今天开始const _maxTime=Date.now()-24*60*60*1000*1return time.getTime()<=_maxTime
}
const dialogFormVisible=computed(()=>prop.isShow)//表单的展示与隐藏绑定在isShow上
const form:Ref<User>=ref<User>({//声明使用User类id:"",date:"",name:"",address:"",order:0
})
watch(()=>prop.info,(newInfo)=>{if(newInfo){form.value={id:newInfo.id,date:newInfo.date,name:newInfo.name,address:newInfo.address,order:newInfo.order }}
})
const emits=defineEmits(["closeAdd","success"])
const closeAdd=()=>{emits("closeAdd")
}
const save=()=>{emits("success")
}</script><style scoped lang="scss">
.dialog-footer button:first-child {margin-right: 10px;
}
.el-button--text {margin-right: 15px;
}
.el-select {width: 300px;
}
.el-input {width: 300px;
}
.dialog-footer button:first-child {margin-right: 10px;
}
</style>

2、后端接口的创建与开发

gitee:https://gitee.com/bigcat_li/ASP.NET-Core

安装nuget:sqlSugarCore

Program.cs

var builder = WebApplication.CreateBuilder(args);// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();var app = builder.Build();// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}app.MapGet("/test", () =>//方法("/路径",()=>{})
{return "ok";
});app.Run();

创建Model->User.cs

using SqlSugar;namespace WebApplication1.Model
{public class User{[SugarColumn(IsPrimaryKey = true)]//使用sqlSugar:配置主键public int Id { get; set; }public string Name { get; set; }public DateTime Date { get; set; }public string Address { get; set; }public int Order { get; set; }}
}

创建Data->SqlSugarHelper.cs

using SqlSugar;namespace WebApplication1.Data
{public class SqlSugarHelper{public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig() {ConnectionString= "Data Source=.;Initial Catalog=BookMS;Persist Security Info=True;User ID=sa;Password=123456;Trust Server Certificate=True",DbType=DbType.SqlServer,//数据库类型IsAutoCloseConnection=true,//不手动colse 自动关闭连接},db =>{db.Aop.OnLogExecuting = (sql, pars) =>{Console.WriteLine(sql);//输出sql返回的数据,不影响性能开发阶段可以使用};});}
}

完善SqlSugarHelper.cs实现增删改查数据库的执行语句

using SqlSugar;
using System.Reflection;
using WebApplication1.Model;namespace WebApplication1.Data
{public class SqlSugarHelper{public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig() {ConnectionString= "Data Source=.;Initial Catalog=BookMS;Persist Security Info=True;User ID=sa;Password=123456;Trust Server Certificate=True",DbType=DbType.SqlServer,//数据库类型IsAutoCloseConnection=true,//不手动colse 自动关闭连接},db =>{db.Aop.OnLogExecuting = (sql, pars) =>{Console.WriteLine(sql);//输出sql返回的数据,不影响性能开发阶段可以使用};});/// <summary>/// 初始化数据库/// </summary>/// <returns></returns>public static string InitDateBase()//自动创建表使用sqlSuger的配置{try{//创建数据库Db.DbMaintenance.CreateDatabase();//创建表string nspace = "WebApplication1.Model";Type[] ass=Assembly.LoadFrom(AppContext.BaseDirectory+ "WebApplication1.dll").GetTypes().Where(p=>p.Namespace == nspace).ToArray();Db.CodeFirst.SetStringDefaultLength(200).InitTables(ass);//初始化数据Db.Deleteable<User>().ExecuteCommand();//清空数据List<User> list = new List<User>();for(int i = 1; i <= 5; i++){list.Add(new User(){Id = Guid.NewGuid().ToString(),Name="Tom"+i,Date=DateTime.Now,Address="北京路138号",Order=i,});}for (int i = 6; i <= 10; i++){list.Add(new User(){Id = Guid.NewGuid().ToString(),Name = "Tom" + i,Date = DateTime.Now,Address = "北京路138号",Order = i,});}for (int i = 11; i <= 30; i++){list.Add(new User(){Id = Guid.NewGuid().ToString(),Name = "Tom" + i,Date = DateTime.Now,Address = "北京路138号",Order = i,});}Db.Insertable(list).ExecuteCommand();return "ok";}catch (Exception ex){return ex.Message;}}///<summary>///1.读取用户列表///</summary>public static Result GetUsers(Model req){Result result = new Result();int total = 0;result.Res = Db.Queryable<User>().WhereIF(!string.IsNullOrEmpty(req.KeyWord), s => s.Name.Contains(req.KeyWord) || s.Address.Contains(req.KeyWord))//过滤数据.OrderBy(s => s.Order)//排序.ToOffsetPage(req.PageIndex, req.PageSize, ref total);//分页result.Total = total;return result;}///<summary>///2.新增///</summary>public static bool Add(AddReq req){User info =new User(){Id=Guid.NewGuid().ToString(),Name = req.Name,Date=req.Date,Address=req.Address,Order=req.Order};if (Db.Queryable<User>().Any(p => p.Name == req.Name)){return false;}return Db.Insertable(info).ExecuteCommand()>0;}///<summary>///3.编辑///</summary>public static bool Edit(User req){User info =Db.Queryable<User>().First(p=>p.Id==req.Id);if (info == null){return false;}info.Name = req.Name;info.Date = req.Date;info.Address = req.Address;info.Order = req.Order;return Db.Updateable(info).ExecuteCommand() > 0;//差不多是返回影响行数的意思}///<summary>///4.删除方法(单个及批量都可以)///</summary>public static bool Del(string ids){return Db.Ado.ExecuteCommand($"DELETE [User] WHERE Id IN({ids})")>0;}}public class Model//分页{public string KeyWord { get; set; }public int PageIndex { get; set; }public int PageSize { get; set; }public int Total {  get; set; }}public class Result//结果{public int Total { get; set; }public object Res { get; set; }}public class AddReq//添加的请求参数{//public string Id { get; set; }public string Name { get; set; }public DateTime Date { get; set; }public string Address { get; set; }public int Order { get; set; }}
}

在Program.cs中追加代码实现网络请求

app.MapGet("/codefrist", () =>
{return SqlSugarHelper.InitDateBase();
});
app.MapPost("/list", (Model req) =>
{return SqlSugarHelper.GetUsers(req);
});
app.MapPost("/add", (AddReq req) =>
{return SqlSugarHelper.Add(req);
});
app.MapPost("/edit", (User req) =>
{return SqlSugarHelper.Edit(req);
});
app.MapDelete("/delete", (string ids) => 
{return SqlSugarHelper.Del(ids);
});

实现对数据库的增删改查

3、前后端链条操作

前端安装:axios

3.1 解决跨域问题

通过代理解决跨域问题

server:{open:true,//自动打开浏览器proxy:{'/api':{target:"http://localhost:5103",//跨域地址 该地址为后端网络请求的前缀changeOrigin:true,rewrite:(path)=>path.replace(/^\/api/,'')}}}

3.2搜索框功能的实现

const enterSearch= async ()=>
{//搜索的功能实现-将输入的内容赋值给关键字,后端实现对数据的检索及重新加载数据userDto.value.keyWord=SearchVal.valueawait load()
}

3.3删除数据的实现(未实现)

要删除数据需要先给表格命名(ref),才能获取表格里的数据

<el-table :data="tableData" style="width: 100%" ref="refTableDataList">
const onDel=async ()=>
{let rows=tableDataListRef.value?.getSelectionRows() as Array<User>//被选中的组成一个数组// console.log(rows)if(rows.length>0){console.log(rows.map(item=>{return `'${item.id}'`}).join(",")); //将id用map方法取出来let res=(await del(rows.map(item=>{return `'${item.id}'`}).join(","))).dataif(res){ElMessage.success("删除成功")await load()}else{ElMessage.success("删除失败")}     }else{ElMessage.warning("请选择需要删除的行")}
}

删除数据不成功报错——405

这个后端删除语句

待解决

3.4实现分页

const handleCurrentChange = async (val: number) => {// 当前点击的值在val中userDto.value.PageIndex=val//将点击获取的值赋值给数据// console.log(userDto);await load()//将页面重新获取一下
}

获取表单验证

给表单添加ref才能获取表单中的数据

 3.5表单校验

const roules=reactive<FormRules>({//对表单进行数据校验 FormRules表单验证规则对象date:[{type:'date',required:true,message:'请选择一个时间',trigger:'chang',}],name:[{required:true,message:'请输入名称',trigger:'blur'}],address:[{required:true,message:'请输入地址',trigger:'blur'}],order:[{required:true,message:'请输入一个序号'},{type:'number',message:'该字段必须是数字'}]
})

如何将表单页传参,实现数据的校验,关于组件间传参数的问题

将表单的数据传入到closeAdd中实现在关闭界面的时候实现校验数据的能力

3.6表单的添加功能不知道为什么(没有实现)

<el-button @click="closeAdd(ruleFormRef)">取消</el-button>
<el-button type="primary" @click="save(ruleFormRef)">确认</el-button>
// TODO 不懂这两行什么意思 突然觉得前端也没那么简单
const closeAdd=async (formE1:FormInstance|undefined)=>{if(!formE1) returnformE1.resetFields()//表单的重置emits("closeAdd")//触发关闭事件}
const save=async (formE1:FormInstance|undefined)=>{//经表单校验??if(formE1) return //如何校验成功await formE1!.validate((valid,fields)=>{if(valid){if(form.value.id){edit(form.value).then(function (res){if(res.data){emits("success","修改成功!")}else{ElMessage.error("操作失败!")}})}else{add(form.value).then(function(res){if(res.data){emits("success","添加成功!")}else{console.log('error submit',fields);}})}}})emits("success")
}

完整的实现的前端代码为:

gitee:https://gitee.com/bigcat_li/configuration

HelloWorld.vue

<template><h2>hello界面</h2><div class="tableList"><!-- 搜索框 --><el-row :gutter="20"><el-col :span="8"><!-- 搜索与添加区域 --><el-input placeholder="请输入内容"v-model="SearchVal" clearable @clear="getUserList" @keyup.enter="enterSearch"><template #append><el-button @click="searchUserList"><el-icon><search /></el-icon></el-button></template></el-input></el-col><el-col :span="2"><el-button type="primary" @click="openAdd">add</el-button></el-col><el-col :span="4"><el-button type="danger" @click="onDel">delete</el-button></el-col></el-row><!-- 表单 --><el-table :data="tableData" style="width: 100%" ref="tableDataListRef"><el-table-column type="selection" width="55" /><el-table-column prop="date" label="Date" width="180" /><el-table-column prop="name" label="Name" width="100" /><el-table-column prop="order" label="Order" width="100" /><el-table-column prop="address" label="Address" /><!-- 操作按钮 --><el-table-column label="Operations"><template #default="scope"><el-button size="small" @click="handleEdit(scope.$index, scope.row)">Edit</el-button><el-buttonsize="small"type="danger"@click="handleDelete(scope.$index, scope.row)">Delete</el-button></template></el-table-column></el-table><el-pagination background layout="prev, pager, next" :total="total"  @current-change="handleCurrentChange"/></div><addVue :isShow="isShow" :info="info" @closeAdd="closeAdd" @success="success"></addVue>
</template><script lang="ts" setup >
import { ref,onMounted } from "vue";
import User from "../class/User.ts"
import addVue from "../components/add.vue"
import UserDto from "../class/UserDto";
import {getList,del} from "../http";
import { ElMessage } from 'element-plus'
const SearchVal=ref("")
const total=ref(100)
// --------------------------
//1.实现的操作是创建属性并去访问它  load调用getList获取返回信息,放在这里一加载就能看见返回的数据
let userDto=ref<UserDto>(new UserDto())
const tableData=ref<any[]>([])//将默认的数据去掉,改成这个格式 响应式的变量<any[]>:类型控制ref([]):响应式的数组
const load=async()=>{console.log(await getList(userDto.value))//value属性去访问它的数据,获取后端的数据let data=(await getList(userDto.value)).datatableData.value=data.restotal.value=data.total
}
onMounted(async()=>{await load()
})
// ----------------------------
const isShow=ref(false)const tableDataListRef=ref()//定义info
const info=ref<User>(new User())const enterSearch= async ()=>
{//搜索的功能实现-将输入的内容赋值给关键字,后端实现对数据的检索userDto.value.keyWord=SearchVal.valueawait load()
}
const searchUserList=async()=>{userDto.value.keyWord=SearchVal.valueawait load()
}
const refresh=() =>{location.reload();}//TODO:清除数据的时候实现原地刷新页面  实现当前页面刷新的方法-最丑陋的刷新方式-后面会使用路由刷新的
const getUserList=async()=>{await load()refresh()
}
const openAdd=()=>{isShow.value=true
}
//TODO:删除数据不成功报405错误
const onDel=async ()=>
{let rows=tableDataListRef.value?.getSelectionRows() as Array<User>//被选中的组成一个数组// console.log(rows)if(rows.length>0){console.log(rows.map(item=>{return `'${item.id}'`}).join(",")); //将id用map方法取出来let res=(await del(rows.map(item=>{return `'${item.id}'`}).join(","))).dataif(res){ElMessage.success("删除成功")await load()}else{ElMessage.success("删除失败")}     }else{ElMessage.warning("请选择需要删除的行")}
}const handleEdit = (index: number, row: User) => {console.log(index, row)info.value=rowisShow.value=true
}
const handleDelete = (index: number, row: User) => {console.log(index, row)
}const handleCurrentChange = async (val: number) => {// console.log(val) 获取值userDto.value.PageIndex=val// console.log(userDto);
await load()//将页面重新获取一下
}const closeAdd=()=>{isShow.value=falseinfo.value=new User()
}
const success=async (message:string)=>{isShow.value=falseinfo.value=new User()ElMessage.success(message)await load()
}// const tableData = [
//   {
//     date: '2016-05-03',
//     name: 'Tom',
//     order:1,
//     address: 'No. 189, Grove St, Los Angeles',
//   },
//   {
//     date: '2016-05-02',
//     name: 'Tom',
//     order:2,
//     address: 'No. 189, Grove St, Los Angeles',
//   },
//   {
//     date: '2016-05-04',
//     name: 'Tom',
//     order:3,
//     address: 'No. 189, Grove St, Los Angeles',
//   },
//   {
//     date: '2016-05-01',
//     name: 'Tom',
//     order:4,
//     address: 'No. 189, Grove St, Los Angeles',
//   },
// ]
</script><style lang="scss" scoped >
.tableList{margin:  0 500px;
}
.el-pagination{margin-top: 20px;
}
</style>

add.vue

<!-- 弹窗组件 -->
<template><el-dialog v-model="dialogFormVisible" :title="info?.name?'修改':'新增'" with="30%" @close="$emit('closeAdd')" draggable="true"><!-- 使用三元表达式控制标题展示 --><el-form :model="form" ref="ruleFormRef" label-width="60px" :rules="rules"><el-form-item label="时间" prop="date"><el-input v-model="form.date" type="date" placeholder="请选择一个时间" :disabledDate="disabledDate"/></el-form-item><el-form-item label="名称" prop="name"><el-input v-model="form.name"></el-input></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="form.address"/></el-form-item><el-form-item label="排序" prop="order"><el-input v-model="form.order"/></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button @click="closeAdd(ruleFormRef)">取消</el-button><el-button type="primary" @click="save(ruleFormRef)">确认</el-button></span></template></el-dialog>
</template>
<script setup lang="ts">
import {ref,Ref,computed,watch, reactive} from "vue"
import User from "../class/User"
import { FormInstance,FormRules } from "element-plus";
import { add, edit } from "../http";
import { ElMessage } from 'element-plus'
const prop=defineProps({//内置的传参工具  接收使用prop传递过来的数据isShow:Boolean,//对于接收的类型进行控制info:User
})
const ruleFormRef=ref<FormInstance>()const disabledDate=(time:any)=>{//最大时间从今天开始const _maxTime=Date.now()-24*60*60*1000*1return time.getTime()<=_maxTime
}
const dialogFormVisible=computed(()=>prop.isShow)//表单的展示与隐藏绑定在isShow上
const rules=reactive<FormRules>({//对表单进行数据校验 FormRules表单验证规则对象date:[{type:'date',required:true,message:'请选择一个时间',trigger:'chang',}],name:[{required:true,message:'请输入名称',trigger:'blur'}],address:[{required:true,message:'请输入地址',trigger:'blur'}],order:[{required:true,message:'请输入一个序号'},{type:'string',message:'该字段必须是数字'}]
})
const form:Ref<User>=ref<User>({//声明使用User类id:"",date:"",name:"",address:"",order:0
})
watch(()=>prop.info,(newInfo)=>{if(newInfo){form.value={id:newInfo.id,date:newInfo.date,name:newInfo.name,address:newInfo.address,order:newInfo.order }}
})const emits=defineEmits(["closeAdd","success"])
// TODO 不懂这两行什么意思 突然觉得前端也没那么简单
const closeAdd=async (formE1:FormInstance|undefined)=>{if(!formE1) returnformE1.resetFields()//表单的重置emits("closeAdd")//触发关闭事件}
const save=async (formE1:FormInstance|undefined)=>{//经表单校验??if(formE1) return //如何校验成功await formE1!.validate((valid,fields)=>{if(valid){if(form.value.id){edit(form.value).then(function (res){if(res.data){emits("success","修改成功!")}else{ElMessage.error("操作失败!")}})}else{add(form.value).then(function(res){if(res.data){emits("success","添加成功!")}else{console.log('error submit',fields);}})}}})emits("success")
}</script><style scoped lang="scss">
.dialog-footer button:first-child {margin-right: 10px;
}
.el-button--text {margin-right: 15px;
}
.el-select {width: 300px;
}
.el-input {width: 300px;
}
.dialog-footer button:first-child {margin-right: 10px;
}
</style>

写完之后的感悟:我前端的vue3及element-plus的使用还太浅,尤其的vue3的很多基础的语法规则都不懂,真是见了鬼了。

前后端:后端提供接口,前端调用接口时传递后端需要的参数实现对数据库的处理,前端的东西是依赖后端的接口的,前端调用接口的时候要保证后端接口的运行状态。

前后端链条:就是将后端的接口在前端页面运用起来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/417555.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】磁盘结构 | 文件系统 | 软硬链接

文件的状态有被打开和没有被打开&#xff0c;之前谈到一个文件被进行读写&#xff0c;就要打开加载到内存中&#xff0c;通过对应的系统调用&#xff0c;fd文件描述符的管理&#xff0c;write和read等函数的增删查改。并且借助缓冲区对文件属性和内容的修改。 大部分文件是没有…

SpringAOP以及事务管理和优化处理

Spring的AOP 本篇章中所有的代码都将会放置到git仓库中去&#xff0c;并且会做一个简要的说明。 一、个人理解描述 Spring中所谓的AOP就是在不修改源码的情况下&#xff0c;来进行增强。所谓的增强其实就是在方法执行前后添加一些额外操作。 所谓的增强&#xff0c;就是我们…

Ubuntu使用docker-compose安装chatGPT

ubuntu环境搭建专栏&#x1f517;点击跳转 Ubuntu系统环境搭建&#xff08;十五&#xff09;——使用docker-compose安装chatGPT Welcome to the AI era! 使用docker compose安装 在/usr/local文件夹下创建chatgpt mkdir chatgpt创建docker-compose.yaml vim docker-compos…

什么是OSPF?为什么需要OSPF?OSPF基础概念

什么是OSPF&#xff1f; 开放式最短路径优先OSPF&#xff08;Open Shortest Path First&#xff09;是IETF组织开发的一个基于链路状态的内部网关协议&#xff08;Interior Gateway Protocol&#xff09;。 目前针对IPv4协议使用的是OSPF Version 2&#xff08;RFC2328&#x…

数据库(MySQL库表操作)

目录 1.1 SQL语句基础&#xff08;SQL命令&#xff09; 1.1.1 SQL的简介 1.1.2 SQL语句的分类 1.1.3 SQL语句的书写规范 1.2 数据库操作 1.2.1 查看 1.2.2 自建库 1.2.3 切换数据库 1.2.4 删库 1.3 MySQL字符集 1.3.1 MySQL字符集包括&#xff1a; 1.3.2 utf8 和 u…

性能压力测试:企业成功的关键要素

性能压力测试在现代企业软件开发中扮演着至关重要的角色&#xff0c;它不仅仅是一项技术手段&#xff0c;更是保障企业成功的关键要素。本文将探讨性能压力测试在企业中的重要性&#xff0c;并阐述其对业务稳定性、用户体验和品牌声誉的影响。 一、保障业务稳定性 1、应对高负载…

Java 全栈知识点问题汇总(上)

Java 全栈知识点问题汇总&#xff08;上&#xff09; 1 Java 基础 1.1 语法基础 面向对象特性&#xff1f;a a b 与 a b 的区别3*0.1 0.3 将会返回什么? true 还是 false?能在 Switch 中使用 String 吗?对equals()和hashCode()的理解?final、finalize 和 finally 的不同…

SpringCloud Aliba-Sentinel【中篇】-从入门到学废【5】

&#x1f3b5;歌词分享&#x1f3b5; 岁月在墙上剥落看见小时候。 ——《东风破》 目录 &#x1f953;1.流控规则 &#x1f32d;2. 熔断规则 &#x1f9c8;3.热点规则 &#x1f9c2;4.系统规则 1.流控规则 1.资源名&#xff1a;唯一名称&#xff0c;默认请求路径 2.针对来…

GPT应用_AutoGPT

项目地址&#xff1a;https://github.com/Significant-Gravitas/AutoGPT 1 功能 1.1 整体功能&#xff0c;想解决什么问题 单独使用 ChatGPT 时&#xff0c;只提供基本的聊天&#xff0c;无法实现复杂多步的功能&#xff0c;以及与其它应用交互&#xff0c;如果想提供某种功…

OpenCV实战:控制手势实现无触摸拖拽功能

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天来学习一下如何使用OpenCV来控制手势&#xff0c;瞬间提升操作体验&#xff01;跨越界限&#xff0c;OpenCV手势控制拖拽功能现身。 一、主要步骤及库的功能介绍 1.主要步骤 要实现本次实验&#xff0c;主要步骤如下…

Redis缓存问题解决方案

Redis缓存问题解决方案 为什么使用Redis缓存&#xff1a; 1.在高并发的情况下&#xff0c;大量查询进入数据库&#xff0c;会大量占用数据库的连接&#xff08;默认数据库连接数151&#xff09;,数据库压力过大就会出现connection refuse(数据库连接拒绝)问题&#xff0c; 2.…

Codeforces Round 895 (Div. 3)补题

Two Vessels&#xff08;Problem - A - Codeforces&#xff09; 题目大意&#xff1a;有两个无限容器&#xff0c;目前一个容器中有a克水&#xff0c;另一个容器中有b克水&#xff0c;现有一个大小为cg的容器&#xff0c;我们每次可以从一个无限容器中取任意不大于c克的水&…