Vue
运行时自动打开页面
在package.json中
"scripts": {
"serve": "vue-cli-service serve --open",
"build": "vue-cli-service build"
},
头部
<div style="height: 50px; line-height: 50px;border-bottom: 1px solid #ccc;display: flex">
<div style="width: 200px">后台管理</div>
<div style="flex: 1"></div>
<div style="width: 100px">下拉框</div>
</div>
去除一下框框中空白部分
创建global.css
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
在main.js中引入
import '@/assets/css/global.css'
安装element-plus
npm install element-plus --save
yarn add element-plus
注意,出现了一个错误或BUG,刚开始使用的cnpm下载的,可能是因为我用的yarn管理的,所以一直报错,el组件没有用,最后卸载了重新用yarn下载了一下解决了
安装图标插件
yarn add @element-plus/icons-vue
侧边栏
App.vue中
<nav>
<Header></Header>
<div style="display: flex">
<Aside></Aside>
<router-view style="flex: 1" /> 这个样式让他分成左右两部分
</div>
Aside.vue中
.el-menu-vertical-demo{
min-height: calc(100vh - 50px); calc是计算,此处注意calc(100vh空格-空格50px)
}
表格
<el-table :data="tableData" border stripe style="width: 100%">
<el-table-column prop="date" sortable label="Date"/>
<el-table-column prop="name" label="Name"/>
<el-table-column prop="address" label="Address"/>
</el-table>
属性
border 边框
stripe 斑马纹
sortable 排序
安装axios
yarn add axios
△!△!坑坑坑△!△!上面是@RestController,后端接收数据要控制格式@RequestBody
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/sss")
public Result save(@RequestBody User user){
userService.saveUser(user);
return Result.success();
}
SpringBoot
1.mybatis-plus之联表查询实现
①简单的思路就是将查询的数据进行打包、封装到实体类中
例如实体类中Commodity商品
@TableField(exist = false)
private List<Img> imgList;
@TableField(exist = false) 表示它不是数据库表中的字段
将查询到的图片集合存入到其中
最后将Commodity对象集合返回给前端即可
②★★写Mapper.xml 以购物车模块为例★★
-
在Mapper中编写相应的方法
@Repository public interface CartMapper extends EasyBaseMapper<Cart> { List<Cart> selectCart(@Param("userId")Integer userId); }
-
在resources/目录下创建一个mapperXML文件夹便于管理,在其中放入Mapper.xml文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.com.liucccc.mapper.CartMapper"> <select id="selectCart" resultMap="selectCartMap"> SELECT cart_id,commodity_id,commodity_quantity FROM tab_cart WHERE user_Id=#{userId} </select> <resultMap id="selectCartMap" type="Cart">★★这里type本应写全Bean的路径因为在yaml中配置了所以直接写就行★★ <id property="cartId" column="cart_id"/> <result property="commodityId" column="commodity_id"/> <result property="commodityQuantity" column="commodity_quantity"/> <!--调用CommodityMapper的查询--> <association property="commodity" column="commodity_id" select="cn.com.liucccc.mapper.CommodityMapper.selectOneCommodity"/> </resultMap> </mapper>
-
主启动类里面加入@MapperScan(“cn.com.liucccc.mapper”) 扫包
-
yaml中配置
mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: classpath:mapperXml/*.xml type-aliases-package: cn.com.liucccc.bean
2.商品类别/迭代联表调用:
<select id="getCategoryList" resultMap="getCategoriesMap">
SELECT category_id,`name`,category_level,is_base FROM tab_category WHERE parent_category_id=0
</select>
<!--嵌套查询-->
<select id="getCategories" resultMap="getCategoriesMap">
SELECT category_id,`name`,category_level,is_base FROM tab_category WHERE parent_category_id=#{categoryId}
</select>
<resultMap id="getCategoriesMap" type="Category">
<id property="categoryId" column="category_id"/>
<result property="name" column="name"/>
<result property="categoryName" column="category_name"/>
<result property="categoryLevel" column="category_level"/>
<result property="isBase" column="is_base"/>
<collection property="childrenList" ofType="Category" column="{categoryId=category_id}" select="getCategories"/>
</resultMap>
3.Mybatis-plus insertBatchSomeColumn批量插入
基础的自带的:
不光有个BaseMapper 还有个IService接口,它里面有个saveBatch方法,但它是伪批量提交实际上还是一条一条插入,效能不太行
★★insertBatchSomeColumn批量插入★★
https://blog.csdn.net/qq_50652600/article/details/126038809 别的博主写的博客
-
导入拓展包
<!--拓展包--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-extension</artifactId> <version>3.5.3.1</version> </dependency>
-
在config目录下编写一下内容即可
编写SQL注入器import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn; import java.util.List; public class EasySqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) { // 注意:此SQL注入器继承了DefaultSqlInjector(默认注入器),调用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自带方法 List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo); methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE)); return methodList; } }
-
注册插件在MybatisPlusConfig总配置文件中(就是那个注册分页插件等等的地方)
//批量插入 @Bean public EasySqlInjector easySqlInjector() { return new EasySqlInjector(); }
-
重写BaseMapper,便于以后调用
package cn.com.liucccc.config; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import java.util.Collection; /*重写BaseMapper*/ public interface EasyBaseMapper<T> extends BaseMapper<T> { /** * 批量插入 仅适用于mysql * * @param entityList 实体列表 * @return 影响行数 */ Integer insertBatchSomeColumn(Collection<T> entityList); }
-
调用
//直接继承重写后的BaseMapper即可 public interface CartMapper extends EasyBaseMapper<Cart>
新知!
1.关于对话窗口调用DOM问题
父组件调用子组件
<!--用户注册组件-->
<UserRegister ref="UserRegister"/>
this.$refs.UserRegister.form
配合ref和this.$refs.UserRegister.
对话框中的内容是懒加载的,这意味着在对话框打开之前,默认插槽(个人理解为el-dialog标签内的内容)不会被渲染到DOM上。因此,如果你需要执行一个DOM操作或通过ref访问组件,可在open事件等回调事件中进行。
在本次实验中,我把用户表单放到了一个组件中,在注册时用户时等调用这个组件,但是这样无疑也造成了许多麻烦,比如这里调用子组件的表单信息,因为它懒加载,所以不能直接的、直观的把form数据取出来,在向后台提交数据form的时候无疑产生了问题,无法取到数据。
**(1)**在本次实验中,针对这个问题,数据的传递时,在确认框里面(对话窗点击确定后弹出的)的回调区域调用,猜测都是回调,在生命周期地位相同,所以可以操作到DOM,取到数据
(2)新想法,在el-dialog标签中绑定鼠标点击事件,在点击确定的时候点下的时候,将表单数据传到父组件中新定义的form中,绑定松开鼠标的时候,调用一个三元判断,来确定调用注册的函数还是更新的函数,在对应的函数里编写相应的提交数据的代码,因为将子组件的数据提前存到了父组件中,所以使用起来就没有障碍了,
关于确认框怎么处理,还没有想到好的解决办法,因为想点击确认的时候再提交数据,虽然可以重复写代码,但是会感觉代码有点冗余,有待改进
2.△!△!坑坑坑△!△!
后端接收数据要控制格式@RequestBody
上面是@RestController,后端接收数据要控制格式@RequestBody
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/sss")
public Result save(@RequestBody User user){
userService.saveUser(user);
return Result.success();
}
因为前后端分离了所以要加@RestController而不是Controller
3.id 的封装应该使用Integer
如果用int
的话id
的默认值会是0
,会出现一些问题,比如在mypatisplus
使用save
时就不能使用算法生成id
了,这样会生成id
为0
的数据,如果有唯一或者主键约束的话,下一次生成就会报错。
4.三元运算符和if-else
最根本的区别就是?:是表达式,是有结果以及其他表达式的特性的。而if else是控制语句
关于vue中写if报错,网友说法是对象中不能写if-else,但可以使用三元运算符
错误写法if-else不可使用
if(this.form.id){
request.put("/users/updateUser", this.$refs.UserRegister.form).then(res => {
console.log(res)
this.load()/*刷新表格*/
})
}else{
/*提交表单信息*/
request.post("/users/save", this.$refs.UserRegister.form).then(res => {
console.log(res)
this.load()/*刷新表格*/
})
}
正确写法
/*判断表单中数据有没有id,如果有id那就是要更新,没有就是注册*/
this.form.id?request.put("/users/updateUser", this.$refs.UserRegister.form).then(res => {
console.log(res)
this.load()/*刷新表格*/
}):
/*提交表单信息*/
request.post("/users/save", this.$refs.UserRegister.form).then(res => {
console.log(res)
this.load()/*刷新表格*/
})
原来整体代码
/*新增用户*/
save() {
/*提示框*/
ElMessageBox.confirm(
'您确定提交吗?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
/*如果提交成功,就把注册的弹窗关闭*/
this.dialogVisible = false,
/*判断表单中数据有没有id,如果有id那就是要更新,没有就是注册*/
this.form.id?request.put("/users/updateUser", this.$refs.UserRegister.form).then(res => {
console.log(res)
this.load()/*刷新表格*/
}):
/*提交表单信息*/
request.post("/users/save", this.$refs.UserRegister.form).then(res => {
console.log(res)
this.load()/*刷新表格*/
}),
ElMessage({
type: 'success',
message: '提交成功',
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '取消提交',
})
})
}
5.mybatis-plus中插件的使用
注意:
使用多个功能需要注意顺序关系,建议使用如下顺序
- 多租户,动态表名
- 分页,乐观锁
- sql 性能规范,防止全表更新与删除
总结: 对 sql 进行单次改造的优先放入,不对 sql 进行改造的最后放入
在后端中使用了分页和乐观锁两个插件
//分页查询
@Bean
public MybatisPlusInterceptor pageInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
//注册乐观锁插件
@Bean
public MybatisPlusInterceptor versionInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
6.可以使input背景变成透明的
background: #ffffff00;
或者background-color: rgba(255, 255, 255, 0.247);
7.图标问题
- 绑定型,input框里面的图标
<el-input
:prefix-icon="Search" />
搭配
setup(){
return {
Search
}
}
components:中注册没有用
- 组件型
<el-icon style="vertical-align: middle">
<Search/>
</el-icon>
搭配
components: {
Search
}
8.数字类验证问题
解决“element表单验证输入的数字检测出来是string”的问题
数字类型的验证需要在 v-model 处加上 .number 的修饰符,这是 Vue 自身提供的用于将绑定值转化为 number 类型的修饰符。
v-model.number="age“
9.form居中
父元素:text-align: center
子元素:display: inline-block
10.vue element 数据动态生成 el-menu
根据博主的思路,递归调用组件实现了效果
注意判断时我感觉根据长度判断最好,因为有的时候子节点存在,但是为空
v-if=“menuItem.childrenList.length!=0”
<template>
<template v-for="menuItem in list"
:key="menuItem.categoryId">
<el-sub-menu :index="menuItem.categoryId.toString()" v-if="menuItem.childrenList.length!=0">
<template #title>
<el-icon>
<GoodsFilled/>
</el-icon>
<span>{{menuItem.name}}</span>
</template>
<Aside :list="menuItem.childrenList"> </Aside>
</el-sub-menu>
<el-menu-item :index="menuItem.categoryId.toString() " v-else>
<el-icon><GoodsFilled /></el-icon>
<template #title>{{menuItem.name}}</template>
</el-menu-item>
</template>
</template>
<script>
import {GoodsFilled} from "@element-plus/icons-vue";
export default {
name: "Aside",
props: {
list: {},
},
components: {GoodsFilled,},
}
</script>
<style scoped>
</style>
调用处
<el-menu
default-active="Commodity"
class="el-menu-vertical-demo"
:collapse="isCollapse"
style="max-width: 200px;"
>
<el-menu-item index="Commodity">
<el-icon><Shop /></el-icon>
<template #title>所有商品</template>
</el-menu-item>
<Aside :list="categoryList"></Aside>
</el-menu>
11.组件属性之props
如上例子中
name: "Aside",
props: {
list: {},
},
通过如下可以传递数据
<Aside :list="categoryList"></Aside>
12.vue内置动态组件component使用详解
虽然使用的时候出现了种种问题,但感觉它仍是一个重要的知识点
<component
/*判断有没有子节点*/
:is="menuItem.children ? 'el-submenu' : 'el-menu-item'"
v-for="menuItem in list"
:key="menuItem.id"
:index="menuItem.id.toString()"
>
<template v-if="menuItem.children">
<template slot="title">{{ menuItem.name }}</template>
<本组件 :list="menuItem.children"></本组件>
</template>
<template v-else>
<i :class="menuItem.icon"></i>
<span slot="title">{{ menuItem.name }}</span>
</template>
</component>
其中,根据绑定的is
的值决定拿个组件被渲染。
13.VUE级联选择器,通过props(配置选项)可以控制数据源格式
el-cascader/
emitPath 在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值
14.mySQL数据库相关(级联删除,自增回滚)
①级联删除
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n0NzDOef-1688618603283)(D:\笔记资料\JavaEE笔记\imgs\级联删除.JPG)]
在外键设置里面更改为“CASCADE”,既级联
删除时,被引用的父表某字段删除,子表跟着一起删除
②自增回滚
在日常使用MySQL时,我们手动删除几条记录后,会发现后续的数据主键自增出现不连续的情况
我们可以执行如下代码解决
1.如果删除完数据还没有新增数据,即还没有出现不连贯的数据ID时,执行以下语句:
ALTER TABLE 表名 AUTO_INCREMENT = 1;
2.如果表中已经出现不连贯的数据ID时,执行以下语句进行修改:
修改代码中“表名”,和“自增字段名”即可
SET @auto_id = 0;
UPDATE 表名 SET 自增字段名 = (@auto_id := @auto_id + 1);
ALTER TABLE 表名 AUTO_INCREMENT = 1;
15.运算精度问题(使用bigNumber.js)
下载:
yarn add bignumber.js --S
使用:
-
引入:
-
import { BigNumber } from 'bignumber.js';
-
例子 (自己尝试得出的结论:不知道对不对,两个数运算的时候,只需对其中一个数进行BigNumber转换即可<代码见下>)
-
a = BigNumber(a); b = BigNumber(b); ★★加★★ a.plus(b).toNumber(); //结果需要用toNumber转为普通数字,不加这个转换好像是返回一个BigNumber对象 ★★减★★ a.minus(b).toNumber(); ★★乘★★ a.multipliedBy(b).toNumber(); ★★除★★ a.dividedBy(b).toNumber(); 多个数求和 multiAdd(...params) { let data = BigNumber(0); for (let index = 0; index < params.length; index++) { const element = BigNumber(params[index]); data = data.plus(element); } return data.toNumber(); } multiAdd(1,2,3,4,5); //15 ★★保留两位小数★★ .toNumber之后 .toFixed(2)
★★自己摸索出的结论:不知道对不对两个数运算的时候,只需对其中一个数进行BigNumber转换即可★★
目前看上去没啥问题
sum(){
let a=BigNumber(0.3)
let b = 0.1
return a.minus(b).toNumber();
},
sum2(){
let a=0.3
let b=0.1
return a-b;
}
运算结果:
sum=0.2
sum2=0.19999999999999998
16.MySql DataTime类型 返回值矫正
时间类型返回数据的时候,返回的值不是我想要的年月日时分秒的形式,而是带英文单词的格式
解决办法:
/*将时间格式转换成正常的*/
@JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date createTime;
17.mybatis的xml中调用别的xml的查询方法
<!--调用CommodityMapper的查询-->
<association property="commodity" column="commodity_id" select="cn.com.liucccc.mapper.CommodityMapper.selectOneCommodity"/>
注意:要写全mapper的namespace
18.逻辑删除
-
局部使用
@TableLogic(value = "0",delval = "1") private Integer deleted;
-
全局使用
mybatis-plus: global-config: db-config: logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
在使用insertBatchSomeColumn批量插入的时候,会让自动插入默认值失效
**解决办法:**使用mybatis plus带的自动填充策略
this.setFieldValByName("deleted",0,metaObject);
问题!
1.动态el-menu,折叠文字不隐藏、菜单导航折叠后文字不隐藏
原文链接:https://blog.csdn.net/xixiyuguang/article/details/120289766
简单说就是el-menu用了div
这里研究了一下,发现只要我把el-submenu直接放入到el-menu中是可以的,但是实际业务中做动态路由的时候会带着菜单项也为动态的,那么基本上就会吧菜单项抽离为组件然后循环渲染,但是由于 element-ui 的标签本身希望里面嵌套的是,,之一,但是却嵌套了
注意
2.vue element 数据动态生成 el-menu
原文链接:https://blog.csdn.net/wyk304443164/article/details/124124845
根据这个文章虽然没有实现,因为的问题,就是标题渲染不上去,后来我根据他的思路把component改为template实现了效果,详细见“新知 10.”
<component
:is="menuItem.children ? 'el-submenu' : 'el-menu-item'"
v-for="menuItem in list"
:key="menuItem.id"
:index="menuItem.id.toString()"
>
<template v-if="menuItem.children">
<template slot="title">{{ menuItem.name }}</template>
<本组件 :list="menuItem.children"></本组件>
</template>
<template v-else>
<i :class="menuItem.icon"></i>
<span slot="title">{{ menuItem.name }}</span>
</template>
</component>
其中写法在vue 3中 slot改为v-slot写法不同,
3.数据库字段
在实验中,数据库字段起名字起的不规范,造成了许多麻烦
例如许多表中都有name字段,在查询的时候就会出现 “模棱两可的” 报错
4.横向滚动条
想给它加两个按钮,一个往左翻,一个往右翻,
或者说用滑轮能实现滚动
据这个文章虽然没有实现,因为的问题,就是标题渲染不上去,后来我根据他的思路把component改为template实现了效果,详细见“新知 10.”
<component
:is="menuItem.children ? 'el-submenu' : 'el-menu-item'"
v-for="menuItem in list"
:key="menuItem.id"
:index="menuItem.id.toString()"
>
<template v-if="menuItem.children">
<template slot="title">{{ menuItem.name }}</template>
<本组件 :list="menuItem.children"></本组件>
</template>
<template v-else>
<i :class="menuItem.icon"></i>
<span slot="title">{{ menuItem.name }}</span>
</template>
</component>
其中写法在vue 3中 slot改为v-slot写法不同,
3.数据库字段
在实验中,数据库字段起名字起的不规范,造成了许多麻烦
例如许多表中都有name字段,在查询的时候就会出现 “模棱两可的” 报错
4.横向滚动条
想给它加两个按钮,一个往左翻,一个往右翻,
或者说用滑轮能实现滚动
没有实现