day19_添加修改删除
day19_添加修改删除
1.前端axios请求的封装
1.1axios公共参数 请求方法二次封装

对axios请求做二次封装
import axios from 'axios'
//技术的二次封装
//公共参数配置
//可以有公共的请求url协议 地址 路径
//如果路径中给的是带协议的完整路径 优先走完整路径
axios.defaults.baseURL = 'http://localhost:8080/baseProj';
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
//跨域时发送cookie 为了使用session
axios.defaults.withCredentials = true
//无session模式 自己传请求头里 放票据信息 后端自己存缓存 自己判断
//请求方式的统一
//使用二次封装的get post请求
const myPost = (currentURL,params)=>{// 发起一个post请求return axios({method: 'post',url: currentURL,data: params});
}
const myGet = (currentURL,params)=>{
return axios({method: 'get',url: currentURL,params: params});
}
//导出对象
export {axios,myPost,myGet};
需要使用时 导入(重复项统一控制)

1.2异步请求同步控制语法
async await
异步请求 默认情况下 谁先回来谁先执行 如果要控制先后顺序 需要嵌套使用
或者使用新语法//为了控制异步请求 同步(依次一个一个执行)执行//需要嵌套调用ajax请求 回调地狱
//async 异步请求同步控制的语法//await 异步请求同步等待 必须等返回值获取 才能继续执行//经过await修饰的异步js代码 必须得到返回值后 在会继续向后执行
// let resp2 = await myPost("/menus/query")// console.log(resp2.data);// let resp = await myGet("/menus/querySelect")// console.log(resp.data);注意:await 不能单独直接使用 函数被async修饰后 才能用await语法
示例:
//公共查询函数
const queryData = async(params)=>{// 获取菜单列表
let resp = await myPost("/menus/query",params)//处理接口响应 都需要根据响应状态码 做判断if(resp.data.code == 20000){tableData.tableList = resp.data.returnDatatableData.pageInfo = resp.data.pageInfo}else if(resp.data.code == 20001){tableData.tableList = []tableData.pageInfo = {page:1,pageSize:10,total:0}}
// myPost("/menus/query",params)// .then(resp=>{// //处理接口响应 都需要根据响应状态码 做判断// if(resp.data.code == 20000){// tableData.tableList = resp.data.returnData// tableData.pageInfo = resp.data.pageInfo// }else if(resp.data.code == 20001){// tableData.tableList = []// tableData.pageInfo = {page:1,pageSize:10,total:0}// }// })
}async await 也可以作为语法糖使用 省略掉.then的函数调用
2.菜单添加
场景分析

sql分析
-- 添加菜单 insert into admin_menu (mid,menuname,pid,url,glyphicon) VALUES (11,'test',16,'/test','ChatLineRound') -- 检测菜单编号是否重复 select * from admin_menu where mid = 1111
编码
菜单接口
protected void insert(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {//1接收参数 封装对象req.setCharacterEncoding("utf-8");String midStr = req.getParameter("mid");String menuname = req.getParameter("menuname");String pidStr = req.getParameter("pid");String url = req.getParameter("url");String glyphicon = req.getParameter("glyphicon");Long pid = null;if(pidStr!=null&&!"".equals(pidStr)){pid = Long.parseLong(pidStr);}Long mid = null;if(midStr!=null&&!"".equals(midStr)){mid = Long.parseLong(midStr);}AdminMenu inputMenu = new AdminMenu(mid, menuname, pid, url, glyphicon);
//调用serviceAdminMenuServiceImpl adminMenuService = new AdminMenuServiceImpl();Integer resNum = adminMenuService.insertMenu(inputMenu);
//3根据结果反馈数据ReturnResult returnResult = new ReturnResult();if(resNum>0){returnResult.setCode(ReturnCode.DATA_OPERATION_SUCCESS.getCode());returnResult.setMsg(ReturnCode.DATA_OPERATION_SUCCESS.getMsg());}else{returnResult.setCode(ReturnCode.DATA_OPERATION_FAILED.getCode());returnResult.setMsg(ReturnCode.DATA_OPERATION_FAILED.getMsg());}
//输出json数据resp.setContentType("application/json;charset=utf-8");PrintWriter writer = resp.getWriter();writer.print(JSON.toJSONString(returnResult));writer.close();
}
protected void checkMid(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {String midStr = req.getParameter("mid");Long mid = null;if(midStr!=null&&!"".equals(midStr)){mid = Long.parseLong(midStr);}AdminMenuServiceImpl adminMenuService = new AdminMenuServiceImpl();AdminMenu menuById = adminMenuService.getMenuById(mid);ReturnResult returnResult = null;if(menuById==null){//可用returnResult = new ReturnResult(ReturnCode.DATA_CHECK_SUCCESS.getCode(), ReturnCode.DATA_CHECK_SUCCESS.getMsg());}else{//不可用returnResult = new ReturnResult(ReturnCode.DATA_CHECK_FAILED_MID.getCode(), ReturnCode.DATA_CHECK_FAILED_MID.getMsg());}
//输出json数据resp.setContentType("application/json;charset=utf-8");PrintWriter writer = resp.getWriter();writer.print(JSON.toJSONString(returnResult));writer.close();
}添加页面
使用弹出框(在页面中 合并其他功能)

前端数据校验:
1配合vue中的事件 发送ajax请求 页面做弹窗
const checkMid = async ()=>{let resp = await myPost('/menus/checkMid',{mid:insertForm.mid})if(resp.data.code == 30011){ElMessage.warning(resp.data.msg)}}这种方式 跟UI的校验 混合使用 不好看 而且需要手动控制总校验
2配合UI库的校验框架 做自定义校验
//添加表单组件
const insertFormRef = ref()
//自定义校验mid
const validateMid = async (rule,value,callback)=>{if(value == ''){callback(new Error('必填项 请输入mid'))}else{let resp = await myPost('/menus/checkMid',{mid:value})if (resp.data.code == 30011) {callback(new Error(resp.data.msg))} else {callback()}}
}
//添加表单校验规则
const rules = reactive({mid: [{ validator: validateMid, trigger: 'blur' }],
})
//提交时的校验
const insertSubmit = async ()=>{//统一校验所有校验规则 如果没成功不让提交insertFormRef.value.validate(async(valid) => {if (valid) {//校验成功//关框insertVisable.value = false
// console.log('发送ajax请求',insertForm);let resp = await myPost('/menus/insert',insertForm)//弹框执行结果if(resp.data.code == 30000){ElMessage.success(resp.data.msg)}else if(resp.data.code == 30001){ElMessage.error(resp.data.msg)}//根据当前查询条件和页码 刷新数据//把两个json对象合并成一个对象let allParams = {...tableData.pageInfo,...queryForm}//合并对象之后 直接发送queryData(allParams)} else {//这个分支可以删掉不要console.log('error submit!')}})
}

解决渲染时机冲突的函数 nextTick
这段代码会报错 但是不影响使用
//添加功能
const openInsertDialog = ()=>{//开框insertVisable.value = true
// //清空表单insertFormRef.value.resetFields()
}注意 :1.弹出框界面中的元素 没弹出之前 不在dom树上
2.渲染时机由vue自动控制 dom元素还没渲染出来 就调用了清空 所以 insertFormRef.value是undefined 找不到
解决方式:
1.绕过错误代码 (通过if避免代码执行)
2.使用nextTick函数 控制渲染和执行时机 (nextTick 让代码的执行时机延后到一次渲染之后)
//添加功能
const openInsertDialog = ()=>{//开框insertVisable.value = true// //清空表单// if(insertFormRef.value != undefined){// //弹出框界面中的元素 没弹出之前 不在dom树上// insertFormRef.value.resetFields()// }//使用了vue之后 自动渲染(时机不能主动控制)//会增加渲染次数 尽量少用//nextTick 让代码的执行时机延后到一次渲染之后nextTick(()=>{console.log(11111);insertFormRef.value.resetFields()})}3菜单修改
场景分析

sql分析
-- 查要修改的数据 select * from admin_menu where mid = 1111-- 修改语句 update admin_menu set menuname = '张飞吃萝卜',pid = 0,url= '/萝卜',glyphicon = 'ChatLineRound' where mid = 21
编码
修改接口
protected void getMenuById(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {String midStr = req.getParameter("mid");Long mid = null;if(midStr!=null&&!"".equals(midStr)){mid = Long.parseLong(midStr);}AdminMenuServiceImpl adminMenuService = new AdminMenuServiceImpl();AdminMenu menuById = adminMenuService.getMenuById(mid);//查到需要修改的菜单信息 返回给页面ReturnResult returnResult = new ReturnResult(ReturnCode.QUERY_SUCCESS.getCode(),ReturnCode.QUERY_SUCCESS.getMsg(),menuById);//输出json数据resp.setContentType("application/json;charset=utf-8");PrintWriter writer = resp.getWriter();writer.print(JSON.toJSONString(returnResult));writer.close();}protected void updateMenu(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {//1接收参数 封装对象req.setCharacterEncoding("utf-8");String midStr = req.getParameter("mid");String menuname = req.getParameter("menuname");String pidStr = req.getParameter("pid");String url = req.getParameter("url");String glyphicon = req.getParameter("glyphicon");Long pid = null;if(pidStr!=null&&!"".equals(pidStr)){pid = Long.parseLong(pidStr);}Long mid = null;if(midStr!=null&&!"".equals(midStr)){mid = Long.parseLong(midStr);}AdminMenu inputMenu = new AdminMenu(mid, menuname, pid, url, glyphicon);//调用serviceAdminMenuService adminMenuService = new AdminMenuServiceImpl();Integer resNum = adminMenuService.updateMenu(inputMenu);//3根据结果反馈数据ReturnResult returnResult = new ReturnResult();if(resNum>0){returnResult.setCode(ReturnCode.DATA_OPERATION_SUCCESS.getCode());returnResult.setMsg(ReturnCode.DATA_OPERATION_SUCCESS.getMsg());}else{returnResult.setCode(ReturnCode.DATA_OPERATION_FAILED.getCode());returnResult.setMsg(ReturnCode.DATA_OPERATION_FAILED.getMsg());}//输出json数据resp.setContentType("application/json;charset=utf-8");PrintWriter writer = resp.getWriter();writer.print(JSON.toJSONString(returnResult));writer.close();}
修改页面
注意:修改表单数据 要从后端加载 为了方便覆盖对象 把属性设置到子对象中 可以统一覆盖
//修改表单(能统一覆盖对象)
const updateForm = reactive({updateData:{mid:'',menuname:'',pid:'',url:'',glyphicon:''
}} )//修改表单(不能统一覆盖对象)
const updateForm = reactive({mid:'',menuname:'',pid:'',url:'',glyphicon:''
} )4删除功能
场景分析

sql分析
-- 做成动态sql delete from admin_menu where mid in (11,12,13,14)
编码
删除接口
protected void deleteMenu(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {//1接收参数 封装对象req.setCharacterEncoding("utf-8");//listMid 11,12,13,14String listMidStr = req.getParameter("listMid");List<Long> listMid = new ArrayList<>();if(listMidStr!=null&&!"".equals(listMidStr)){//给listMid装数据for(String midStr: listMidStr.split(",")){listMid.add(Long.parseLong(midStr));}}//调用serviceAdminMenuService adminMenuService = new AdminMenuServiceImpl();Integer resNum = adminMenuService.deleteMenuMultiple(listMid);//3根据结果反馈数据ReturnResult returnResult = new ReturnResult();if(resNum>0){returnResult.setCode(ReturnCode.DATA_OPERATION_SUCCESS.getCode());returnResult.setMsg(ReturnCode.DATA_OPERATION_SUCCESS.getMsg());}else{returnResult.setCode(ReturnCode.DATA_OPERATION_FAILED.getCode());returnResult.setMsg(ReturnCode.DATA_OPERATION_FAILED.getMsg());}//输出json数据resp.setContentType("application/json;charset=utf-8");PrintWriter writer = resp.getWriter();writer.print(JSON.toJSONString(returnResult));writer.close();}删除页面
使用ElmessageBox 预制的确认框(不需要写界面 只需要做配置)
//删除开框
const openDeleteDialog = ()=>{let rowData = tableRef.value.getSelectionRows()//是否选中了值if(rowData.length>0){//获取数据 弹确认框console.log(rowData);//给后端传的let listMidArr = []//给用户看的let listMidInfo = []rowData.forEach(row => {listMidArr.push(row.mid)listMidInfo.push(`${row.mid}-${row.menuname}`)});let listMidStr = listMidArr.join(",")//最后要 字符串 11,12,13,14ElMessageBox.confirm(`确认要删除[${listMidInfo}]的数据么`,'警告',{confirmButtonText: '删除',cancelButtonText: '取消',type: 'warning',}).then(() => {//console.log("点了删除");// 调用公共函数operationData('/menus/deleteMenu',{listMid:listMidStr})}).catch(() => {console.log("点了取消");})}else{//没选中 弹窗提示ElMessage.warning("请先选择数据")}}