赞
踩
前端:Vue3,Vite,TypeScript,SCSS,Element Plus,Router,axios
后端:.NET6,Minimal API,Sql sugar(CodeFirst)
根据哔哩哔哩视频整理的,比较详细了,建议先根据文档写,有问题再看代码,记忆比较深刻。
代码已上传.
哔哩哔哩视频地址:001.教学演示和技术栈介绍_哔哩哔哩_bilibili
------------------------------------------------------------安装环境---------------------------------------------------
安装nodejs:
开发vue项目需要通过那npm指令,安装这个只是为了使用npm命令
下载地址:http://nodejs.cn/download/
下载是否成功测试:node --version
安装pnpm:
官网:https://www.pnpm.cn/
安装:npm install -g pnpm@next-7
相比npm更快更稳定,所有使用npm安装包的命令都能替换成pnpm;pnpm dev等价于npm run dev
创建前端项目:
新建文件夹,在文件夹路径进入cmd,执行指令:pnpm create vite@latest web(web为项目名称)
指令执行完毕会返回一些打印,让你选择项目模板,按上下键选择,我们选择Vue然后回车
再次选择TypeScript
然后会返回一些打印,提示你运行的步骤
用VSCODE打开项目:
文件-->打开文件夹-->选择刚才创建的文件
node_modules:模块包(通过install安装的包都在这个目录里面)
public:公共资源(json,images)
src:项目目录
assets:静态资源
components:组件
App.vue:根组件
main.ts:根函数入口,全局配置生效的地方
package.json:项目配置文件,项目的标题,版本,模块的版本等信息
如果没有node_modules文件,只需要在终端执行pnpm install即可
vite.config.ts文件可以配置ip和端口,以及启动后是否默认打开浏览器
- server:{
- host:"127.0.0.1",
- port:3001,
- open:true
- }
- server:{open: true} //自动打开浏览器
安装sass
官网介绍:https://www.sass.hk/guide/
命令:pnpm install sass
目的:支持嵌套css编写;支持定义变量
安装路由(多界面相互之间跳转):
介绍:https://router.vuejs.org/zh/introduction.html
指令:pnpm install vue-router@4
测试:
src下新建router文件夹下新建index.ts文件
import { createRouter, createWebHistory } from 'vue-router'
src下新建views文件夹下新建HomePage.vue与TestPage.vue文件,格式如下,内容不同
HomePage.vue:
- <template>
- <div>0000</div>
- </template>
-
- TestPage.vue:
- <template>
- <div>1111</div>
- </template>
在main.ts中配置路由,增加下面两行
- import router from './router/index'
- create(App).use(router).mount('#app')
router文件夹下index.ts配置
- import {createRouter,createWebHistory} from 'vue-router'
- var router=createRouter({
- history:createWebHistory(),
- routes:[
- {name:"home", path:"/", component: () => import("../views/HomePage.vue")}, //name:路由名字;path:路由路径;import:路由组件
- {name:"test", path:"/test", component: () => import("../views/TestPage.vue")}
- ]
- })
- export default router
解决./App.vue或者其他.vue文件报错,在vite-env.d.ts增加以下代码解决(ts需要固定格式,这里跳过格式检查)
- declare module '*.vue' {
- import { App, defineComponent } from 'vue'
- const component: ReturnType<typeof defineComponent> & {
- install(app: App): void
- }
- export default component
- }
在App.vue文件中添加<router-view></router-view>,此标签就是表示把路由页面呈现在哪个地方
------------------------------------------------------集成element-plus--------------------------------------------------
Element Plus
官网介绍:https://element-plus.gitee.io/zh-CN/
安装命令:pnpm install element-plus
在element-plus官网中快速入门
按需引入包:
pnpm install -D unplugin-vue-components unplugin-auto-import
因为我使用的是Vite,所以就用教程的Vite引入,其他自己做的页面的话就用Webpack
首先在vite.config.ts文件中导入:
- import AutoImport from 'unplugin-auto-import/vite'
- import Components from 'unplugin-vue-components/vite'
- import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
再在plugins的vue(),后面添加
- AutoImport({
- resolvers: [ElementPlusResolver()],
- }),
- Components({
- resolvers: [ElementPlusResolver()],
- }),
在HomePage.vue文件里面把element的组件(随便在element官网找几个button按钮组件)写入进去,运行代码,查看是否是element的UI
按需导入后,组件可以使用了,但是少数部分组件会有报错,但是不影响功能,如果想要解决报错信息,需要修改tsconfig.json文件
在include节点里面加入:"**/*.d.ts"即可导入图标:
根据element官网文档
icon图标:先安装包管理器:pnpm install @element-plus/icons-vue
注册所有图标(放在main.ts文件中):
- import * as ElementPlusIconsVue from '@element-plus/icons-vue'
-
- const app = createApp(App)
- for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
- app.component(key, component)
- }
最后一行改为app.use(router).mount('#app')
在HomePage.vue文件加入icon图标代码(element文档Button里面有)
例如:
- <el-button :icon="Search" circle />
- <el-button type="primary" :icon="Edit" circle />
- 还要加入下面的代码
- <script lang="ts" setup>
- import {
- Check,
- Delete,
- Edit,
- Message,
- Search,
- Star,
- } from '@element-plus/icons-vue'
- </script>
如果有报错就把tsconfig.json里面的配置修改为:
- "moduleResolution": "Node",
- "noUnusedLocals": false,
-----------------------------------------------------静态页面的实现-------------------------------------------------------
注释掉main.ts的import './style.css' //不用自带的样式
HomePage.vue增加:
- <template> //页面
- <div></div>
- </template>
- <script lang="ts" setup> //脚本
- </script>
- <style lang="scss" scoped> //scss:样式;scoped:只在本页面有效,不影响其他页面
- </style>
以element组件表格为例,直接复制到HomePage.vue页面
然后在style标签添加:
- .container{ //居中
- margin: 100px auto;
- width: 50%;
- }
- .table{ //表格间距等
- margin: 10px 0;
- }
增加页面的搜索,添加,删除操作:div中增加以下代码
- <el-row>
- <el-col :span="12">
- <el-input v-model="SearchVal" placeholder="Please input" class="input-with-select" @keyup.enter="enterSearch">
- <template #append>
- <el-button :icon="Search" @click="enterSearch"></el-button>
- </template>
- </el-input>
- </el-col>
- <el-col :span="12">
- <el-button type="primary" @click="openAdd">add</el-button>
- <el-button type="danger" @click="onDel">delete</el-button>
- </el-col>
- </el-row>
script标签增加:
- import { ref } from 'vue';
- import { Search } from '@element-plus/icons-vue';
- const SearchVal = ref("")
- const enterSearch=()=>{
-
- }
-
- const onDel=()=>{
-
- }
-
- const openAdd=()=>{
-
- }
增加多选框:
在table里面添加
- <el-table-column type="selection" width="55"></el-table-column> //多选框
- <el-table-column prop="order" label="Order" width="80" /> //排序列
在script数据里面增加字段order,例如:order: 1,在table标签最后一列增加数据后修改与删除按钮(插槽):
- <el-table-column label="Operations">
- <template #default="scope">
- <el-button size="small" @click="handleEdit(scope.$index,scope.row)">Edit</el-button>
- <el-button size="small" type="danger" @click="handleDelete(scope.$index,scope.row)">Delete</el-button>
- </template>
- </el-table-column>
修改与删除按钮实现方法:
- const handleEdit=(index: number, row: any)=>{ //index类型指定number,row类型指定任何数据类型都可以
- console.log(index,row)
- }
-
- const handleDelete=(index: number, row: any)=>{
- console.log(index,row)
- }
在div里面,table外增加分页代码:
<el-pagination background layout="prev,pager,next" :total="total" @current-change="currentChange"></el-pagination>
实现:
const total = ref(100) //最大100页
每页数据:
- const currentChange=(val:number)=>{
- console.log(val)
- }
--------------------------------------------------增加add与edit组件-----------------------------------------------------
components文件夹下增加add.vue文件
使用官网的弹窗组件
- <template>
- <el-dialog v-model="dialogVisible" title="新增" width="30%">
- <el-form>
- <el-form-item label="时间" prop="date">
- <el-date-picker v-model="form.date" type="date" placeholder="请选择一个时间" :disabled-date="disablesDate"></el-date-picker>
- </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-input>
- </el-form-item>
- <el-form-item label="排序" prop="order">
- <el-input v-model.number="form.order"></el-input>
- </el-form-item>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="closeAdd()">Cancel</el-button>
- <el-button type="primary" @click="save()">Confirm</el-button>
- </span>
- </template>
- </el-dialog>
- </template>
- <script lang="ts" setup>
- import { ref } from 'vue' //导入ref
- const dialogVisible = ref(false) //控制显示与隐藏,默认不显示
- const form = ref()
- const disablesDate = (time: any) =>{
- //最大时间,从今天开始,只能选今天及以后的时间
- const _maxTime = Date.now() - 24 * 60 * 60 * 1000 * 1
- return time.getTime() <= _maxTime
- }
-
- const closeAdd = () =>{
-
- }
-
- const save = () =>{
-
- }
-
- </script>
------------------------------------------页面引用组件(实现点击按钮跳出弹框)-------------------------------------
在src下新建class文件夹,class文件夹下新建User.ts文件
- export default class User{ //导出一个默认User类
- id: string = ""
- date: string = ""
- name: string = ""
- address: string = ""
- order: number = 0
- }
add.vue文件修改:
- import { ref,Ref,computed } from 'vue' //导入ref与计算函数computed和Ref表单
- import User from '../class/User' //导入User对象
- const props = defineProps({ //定义一个对象,defineProps为内置函数,用于接收参数
- isShow: Boolean, //控制弹窗的弹出与隐藏的参数
- info: User //对象类型(参数)
- })
- const dialogVisible = computed(()=>props.isShow) //控制弹窗显示与隐藏,实现props中isShow与dialogVisible值的联动
定义一个表单:
- const form: Ref<User> = ref<User>({ //声明form是User类型
- id: "",
- date: "",
- name: "",
- address: "",
- order: 0
- })
修改HomePage.vue页面
导入弹窗:
<addVue :isShow = "isShow"></addVue>
导入add和User:
- import addVue from '../components/add.vue'; //将add.vue导入
- import User from '../class/User'; //将User导入
如果addVue报错,禁用Vetur插件,使用Vue Language Features插件
设置默认不显示:
const isShow = ref(false)
数据来源:
const info = ref<User>(new User()) //数据
修改与删除控制:
- const handleEdit=(index: number, row: User)=>{ //row:数据类型
- console.log(index,row)
- info.value = row //编辑时赋值
- isShow.value = true //点击编辑时修改为显示
- }
- const handleDelete=(index: number, row: User)=>{
- console.log(index,row)
- }
- const openAdd=()=>{ //添加时也显示
- isShow.value = true
- }
运行测试,点击add和edit就可以跳出弹窗
------------------------------------------------------侦听器Watch()-------------------------------------------------------
作用:将页面form与数据info绑定
修改HomePage.vue页面
导入弹窗:
<addVue :isShow = "isShow" :info = "info"></addVue> //增加info,将数据传入
修改add.vue,修改title:
:title="info?.name ? '修改' : '新增'" //改为根据客户点击add还是edit改变title
import { ref, Ref, computed, watch } from 'vue' //增加watch
- watch(() => props.info,(newInfo) => { //监听props.info值,如果info值改变,则将改变后的值赋值给newInfo,将newInfo值重新赋值给info;其实这里有两个参数,后面还有一个oldInfo(修改前的数据),但是我们这里用不到
- if(newInfo){ //如果newInfo值改变,则重新对form表单进行赋值
- form.value = {
- id: newInfo.id,
- date: newInfo.date,
- name: newInfo.name,
- address: newInfo.address,
- order: newInfo.order
- }
- }
- })
-------------------------------------------------子组件触发父组件事件--------------------------------------------------
在add.vue中定义两个事件:
const emits = defineEmits(["closeAdd","success"])
修改closeAdd事件:
- const closeAdd = () => {
- emits("closeAdd") //执行closeAdd事件
- }
修改save事件:
- const save = () => {
- emits("success") //执行success事件
- }
在子组件触发了父组件的事件,父组件要定义对应事件;在HomePage.vue中定义closeAdd事件与success事件:
- const closeAdd = () => {
- isShow.value = false //关闭弹窗
- info.value = new User() //数据值初始化
- }
- const success = (message: string) => { //加参数打印成功
- isShow.value = false
- info.value = new User()
- ElMessage.success(message) //成功弹窗出来
- }
将事件绑定到弹窗,修改addVue标签
<addVue :isShow="isShow" :info="info" @closeAdd="closeAdd" @success="success"></addVue>
修改add.vue,实现弹窗右上角关闭(x)功能:
在<el-dialog>标签中添加@close="$emit('closeAdd')"
在<el-dialog>标签中添加draggable,实现弹窗随意拖动效果
---------------------------------------------------.NET Core Minimal API----------------------------------------------
打开VS2019 --> 创建新项目 --> 选择ASP.NET Core Web API --> 下一步 --> 修改项目名称和位置 --> 下一步 --> 启用OpenAPI支持,其他不用选 --> 创建
进入Program,删除app.MapGet默认接口,改为:
- if (app.Environment.IsDevelopment())
- {
- app.UseSwagger();
- app.UseSwaggerUI();
- }
- //极简API接口,MapGet:访问方式
- app.MapGet("/test", () =>
- {
- return "ok";
- });
- app.Run();
运行后会到swagger UI,调试成功即可
------------------------------------------------------SqlSugar介绍与安装-----------------------------------------------
官网:
介绍:https://www.donet5.com/Home/Doc
教学:https://www.donet5.com/Doc/29
是一款老牌的.NET开源ORM框架
项目安装引用:
在解决方案资源管理器中右键依赖项 --> 管理NuGet程序包 --> 浏览 --> 输入sqlsugarcore --> 点击后安装即可
安装完成后在项目目录的依赖项下的包下就会看到sqlsugarcore的包,说明安装成功
根目录下新建Model文件夹,Model文件夹中新建User实体类
User内容:
- public class User
- {
- [SugarColumn(IsPrimaryKey = true)] //设置为主键
- 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; }
- }
波浪线无影响,如需要去掉,鼠标放在波浪线,找到无提示即可
--------------------------------------------------------实现CodeFirst-----------------------------------------------------
1.根据数据库中的字符串信息,动态创建数据库
2.通过反射读取当前程序集下的类,然后创建表
3.添加测试数据到数据库,完成初始化根目录下创建Data文件夹,Data文件夹下创建SqlSugarHelper辅助类
- public class SqlSugarHelper
- {
- public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig()
- {
- ConnectionString = "server=127.0.0.1;uid=root;pwd=admin;database=myDatabase",
- DbType = DbType.MySql,//设置数据库类型(我用的MySQL,根据自己的需要修改)
- IsAutoCloseConnection = true,//自动释放数据务,如果存在事务,在事务结束后释放
- InitKeyType = InitKeyType.Attribute //从实体特性中读取主键自增列信息
- },
- db =>
- {
- //打印sql日志,调试阶段可以开着,方便调试
- db.Aop.OnLogExecuting = (sql, pars) =>
- {
- Console.WriteLine(sql);
- };
- }
- );
-
-
- //初始化数据库
- public static string InitDateBase()
- {
- try
- {
- //创建数据库
- Db.DbMaintenance.CreateDatabase();
- //初始化数据表,如果没有则创建
- string nspace = "api.Model"; //过滤,表示只使用api.Model下的类(User)
- //LoadFrom可以加载AppContext.BaseDirectory程序集下的api.dll文件;GetTypes获取dll文件下的所有类;使用where过滤,确保拿到的是api.Model下的文件
- Type[] ass = Assembly.LoadFrom(AppContext.BaseDirectory + "api.dll").GetTypes().Where(p => p.Namespace == nspace).ToArray();
- Db.CodeFirst.SetStringDefaultLength(200).InitTables(ass); //初始化table
- //添加数据前清空数据
- 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 = "No. 189, Grove St, Los Angeles",
- Order = i
- });
- }
-
- for (int i = 6; i <= 10; i++)
- {
- list.Add(new User()
- {
- Id = Guid.NewGuid().ToString(),
- Name = "Tom" + i,
- Date = DateTime.Now,
- Address = "No. 129, Grove St, Los Angeles",
- Order = i
- });
- }
-
- for (int i = 11; i <= 30; i++)
- {
- list.Add(new User()
- {
- Id = Guid.NewGuid().ToString(),
- Name = "Tom" + i,
- Date = DateTime.Now,
- Address = "No. 87, Grove St, Los Angeles",
- Order = i
- });
- }
- //添加到表中
- Db.Insertable(list).ExecuteCommand();
- return "ok";
- }
- catch(Exception ex)
- {
- return ex.Message;
- }
- }
-
- }
-------------------------------------------------------------写接口-----------------------------------------------------------
实体类(正常情况是要新建类,但是demo为了方便,直接写在接口下面)
- 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 Name { get; set; }
- public DateTime Date { get; set; }
- public string Address { get; set; }
- public int Order { get; set; }
- }
写查询方法:
- //分页查询
- public static Result GetUsers(Model req)
- {
- Result result = new Result();
- int total = 0;
- result.Res = Db.Queryable<User>() //sql查询
- .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;
- }
写添加方法:
- 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)) //判断是否存在,存在则返回false
- {
- return false;
- }
- return Db.Insertable(info).ExecuteCommand() > 0; //不存在则插入到数据库里面,并且返回插入成功或者失败
- }
写修改方法:
- public static bool Edit(User req)
- {
- User info = Db.Queryable<User>().First(p => p.Id == req.Id); //先读一遍
- if (info == null) //判断是否存在,不存在则返回false
- {
- return false;
- }
- //存在则赋值
- info.Name = req.Name;
- info.Date = req.Date;
- info.Address = req.Address;
- info.Order = req.Order;
- return Db.Updateable(info).ExecuteCommand() > 0; //更新数据,并且返回更新成功或者失败
- }
//删除方法
- public static bool Del(string ids)
- {
- return Db.Ado.ExecuteCommand($"DELETE from `User` WHERE Id IN({ids})") > 0;
- }
在Program文件中增加接口实现:
- app.MapGet("/codefirst", () =>
- {
- 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.MapGet("/del", (string ids) =>
- {
- return SqlSugarHelper.Del(ids);
- });
运行代码,会自动跳转到页面
先执行/codefirst初始化数据库
再执行/list,将条件换成全查条件,查看输出是否正确
------------------------------------------------------前后端数据交互------------------------------------------------------
axios的安装与使用:
官网介绍:http://www.axios-js.com/
安装命令:
pnpm install axios
在前端src文件夹下新建一个文件夹http(所有请求都放在这个文件夹里面)
在http下新建文件index.ts
在index.ts中写:
- import axios from 'axios'
- import UserDto from '../class/UserDto'
- //查询
- export const getList = (req: UserDto) => {
- return axios.post("/api/list",req)
- }
- //新增
- export const add = (req: {}) => {
- return axios.post("/api/add",req)
- }
- //修改
- export const edit = (req: {}) => {
- return axios.post("/api/edit",req)
- }
- //删除
- export const del = (ids: string) => {
- return axios.get("/api/del?ids="+ids)
- }
在class文件夹下新建文件:UserDto.ts
- export default class UserDto{ //列表分页参数传到后端
- keyWord: string = ""
- PageIndex: number = 1
- PageSize: number = 10
- }
修改HomePage.vue
增加:
导入UserDto:import UserDto from '../class/UserDto';
导入getList:import {getList} from '../http';
- let userDto = ref<UserDto>(new UserDto())
- const load = async()=>{
- console.log(await getList(userDto.value))
- }
实现页面加载时请求数据
import { ref } from 'vue'改为import { ref,onMounted } from 'vue' //定义关键字
增加:
- onMounted(async () => { //在页面加载时执行load方法
- await load()
- })
运行代码,F12显示跨域问题
---------------------------------------------------------解决跨域问题------------------------------------------------------
浏览器显示CORS问题,原因是前端IP和后端IP不匹配导致,浏览器出于同源策略的安全性校验不允许直接访问资源,则会返回跨域错误
解决:通过代理解决
在vite.config.ts文件中修改server配置:
- server:{
- open: true, //自动打开浏览器
- proxy:{
- '/api':{
- target:"http://localhost:5173",
- changeOrigin:true,
- rewrite(path){
- return path.replace(/^\/api/,'')
- }
- }
- }
- }
在index.ts中修改接口:
http://localhost:5173改为/api
-----------------------------------------------------------列表页数据联调-------------------------------------------------
HomePage.vue增加:
const tableData = ref<any[]>([]) //把默认数据改为读接口数据(定义ref响应式变量,any类型数组)
修改:
- const load = async () => {
- let data = (await getList(userDto.value)).data //将接口数据放入变量data
- tableData.value = data.res //接口数据给到table表格
- total.value = data.total //total数据也给到表格
- }
实现搜索功能:
修改:
- const enterSearch = async () => {
- userDto.value.keyWord = SearchVal.value //将搜索框中的值传入userDto.value.KeyWord作为条件
- await load() //重新请求
- }
实现删除功能:
el-table标签中增加ref="multipleTableRef"
定义:
const multipleTableRef = ref()
导入删除方法:
import {getList} from '../http'改为import {getList,del} from '../http'
修改删除方法:
- const onDel = async() => {
- let rows = multipleTableRef.value?.getSelectionRows() as Array<User> //获取到复选框选中的数据
- if(rows.length > 0){ //如果选中的值大于0
- console.log(rows.map(item => {return `'${item.id}'`}).join(","))
- //在${item.id}外层加一个单引号是为了序列化成字符串,结果示例:'a','b','c',传到后端放在in查询里面
- let res = (await del(rows.map(item => {return `'${item.id}'`}).join(","))).data
- if(res){
- ElMessage.success("删除成功!")
- await load()
- }else{
- ElMessage.error("删除失败!")
- }
- }else{
- ElMessage.waring("请选中需要删除的行!")
- }
- }
实现分页效果:
修改currentChange方法:
- const currentChange = async (val: number) => {
- userDto.value.PageIndex = val
- await load()
- }
编辑页表单验证:
add.vue中el-form增加:
:model="form" label-width="60px" ref="ruleFormRef" 用于获取表单
导入用于表单验证的类型:
import {FormInstance,FormRules} from 'element-plus'
获取表单对象:
const ruleFormRef = ref<FormInstance>()
验证规则:
- const rules = reactive<FormRules>({
- date:[{
- type: 'date',
- required: true,
- message: '请选择一个时间',
- trigger: 'change',
- }],
- name:[{
- required: true, message: '请输入名称', trigger: 'blur'
- }],
- address:[{
- required: true, message: '请输入地址', trigger: 'blur'
- }],
- order:[
- {required: true, message: '请输入一个序号'},
- {type: 'number', message: '该字段必须是数字'}
- ]
- })
修改import{...}from 'vue'中增加reactive
在el-form中增加:
:rules="rules"
在Cancel与Confirm按钮中点击事件增加参数ruleFormRef(表单对象)
导入添加和修改方法:
import {add,edit} from '../http'
增加closeAdd与save方法:
- const emits = defineEmits(["closeAdd","success"])
- const closeAdd = async (formEl: FormInstance | undefined) => {
- if(!formEl) return
- formEl.resetFields() //重置表单
- emits("closeAdd")
- }
- const save = async (formEl: FormInstance | undefined) => {
- if(!formEl) return
- await formEl.validate((valid, fields) => {
- if(valid){ //如果表单校验成功,则执行修改或者添加操作
- if(form.value.id){ //如果id存在,执行修改方法
- edit(form.value).then(function (res){
- if(res.data){
- emits("success","修改成功!")
- }
- })
- } else { //如果id不存在,执行添加方法
- add(form.value).then(function (res){
- if(res.data){
- emits("success","添加成功!")
- }
- })
- }
- }else{
- console.log('error submit!', fields)
- }
- })
- }
修改HomePage.vue中success方法:
- const success = async (message: string) => {
- isShow.value = false
- info.value = new User()
- ElMessage.success(message)
- await load()
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。