上周又偷懒了没有按时写博客(扣大分啊啊!)但是好像也没有人看呢~其实最开始也只是想着记录一下实习历程,怕自己之后回过头想关于实习的都想不起来了,个人还是喜欢记录有关自己的学习生活的,就算没啥人看但回过头看不觉得这一段是空白的。
本周总结:
- 重构
- 新增模特弹框
- 更多模特弹框
- 新增场景弹框
- 更多场景弹框
其实是重构了一个项目,老代码一个页面写了一千多行看着好费劲(密密麻麻)。然后现在是按照页面结构还有功能将其抽离成不同的组件了。当然,我,就只是写了很小一部分,大部分还是师父写的(怎么感觉我好像在拖后腿......)。这里就记录一下数据请求之增删改查和一些要注意的点了。
一、查
场景:点击不同的页码显示不同的数据
思路:获取到你点击的页码》将这些参数发送给后端》将后端返回的数据重新赋值到原来的数据》添加页码改变的回调:请求数据列表
(1)获取到你点击的页码
- Ant Design Vue 这里用到的组件是antdv
- 当收集相应的数据时,查找一下对应的API与事件
const tableSet = reactive({
currentPage: 1,//默认
perPage: 35,//默认
totalPage: 0,
});
......
<APagination
v-model:current="tableSet.currentPage"
v-model:page-size="tableSet.perPage"
show-quick-jumper
:total="tableSet.totalPage"
@change="onChange"
/>
(2)将这些参数转化为后端接收的字段发送GET请求给后端,后端返回我们需要的数据
- 这里就自己查看接口文档了看需要携带什么参数,记得将收集到的数据转化为后端需要的字段!
const sceneData = async () => {
const path = '/resource/xxxx';
const params = {
per_page: tableSet.perPage,
page: tableSet.currentPage,
};
const res = await Http.get(path, params);
return {
currentPage: res.data.list.current_page,
perPage: res.data.list.per_page,
totalPage: res.data.list.total,
};
};
(3)将后端返回的数据重新赋值到原来的数据
const getSceneLIst = async () => {
const {currentPage, perPage, totalPage } = await sceneData();
tableSet.currentPage = currentPage;
tableSet.perPage = perPage;
tableSet.totalPage = totalPage;
};
(4)添加页码改变时的回调
const onChange = (page, pageSize) => {
getSceneLIst();
};
二、删
场景:点击选中需要删除的选项,将其从列表中移除,且提示删除成功
思路:获取选项id》携带参数发送请求》刷新列表
(1)获取选项id
- 怎么删除某个选项,一定是根据他的唯一标识来代表他(当然了看后端需要什么参数我们就找)
- 引用的自定义组件
<PicItem
v-for="picInfo in state.dataList"
:key="picInfo.id"
:pic-info="picInfo"
:checked="state.checked.id === picInfo.id"
@update:checked="(b) => onChecked(picInfo, b)"
@model-deleted="modelDeleted"
/>
(2)携带参数发送请求
- 如果你想的单单是带个参数发个请求就OK了 但是不会这么简单的
- 点击删除图标=选中选项,发送删除请求虽然把他删了,但这个选项已经是选中状态了,在最后提交的时候会把这个选项也提交上去!这是不可以的!一定要记得清空鸭
- 最后记得刷新列表获取最新数据哦
const modelDeleted = async (sceneInfo: SceneInfo) => {
state.remove = true;
const path = '/resource/delete';
const params = {
id: sceneInfo.id,
};
await Http.post(path, params);
if (sceneInfo.id === state.checked.id) {
state.checked.id = '';
}
getSceneLIst();
_message.success("sucess");
};
const onChecked = (picInfo: SceneInfo, b: boolean) => {
state.checked = picInfo;
};
三、增
场景:点击提交按钮将自定义的人物信息提交到列表最前方
思路:怎么收集数据发请求就不说了,重点说一下提交时候的一些细节逻辑
- 首先记得表单校验哇
- 为了优化用户体验,记得给点提示!提交按钮添加loading效果
- 其实这里最后逻辑是传给了父组件一并处理的(emits('submitAdd'); 忘了是啥)
- 设计网络请求的多使用try catch finally 更方便捕捉错误
const submitModel = async () => {
try {
if (state.agreement === false) {
_message.error("error");
}
await formRef.value.validate().then(validState);
state.loading = true;
const path = '/resource/create';
const params = {
name: state.name,
type: state.type,
age: state.ageCheckedList[0].id,
...
};
const res = await Http.post(path, params);
emits('submitAdd');
} catch (err) {
console.error(err);
} finally {
state.loading = false;
}
};
说完了增删改查再来看一下其他比较麻烦的点吧。
四、选择变换
场景:选择不同的性别类型切换对应的年龄选项以及要展示的人物图片。
思路1:先说说之前一个比较笨的想法,给这两种类型对应的菜品写两个数组存放,通过v-if判断控制显示隐藏;对应的图片使用选择的回调来显示,但是这样的话要写九种不同的选择对应的九张图片,其实实际场景会有更多图片!
- 可以看到这样写逻辑很繁琐,代码也很冗长
<script setup>
const womanFileUrl =
'https://images.pexels.com/photos/22708188/pexels-photo-22708188.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2';
const womanFile = await urlToFile(womanFileUrl);
const KidFileUrl = 'https://cdn.pixabay.com/photo/2022/11/09/21/12/candle-7581472_1280.jpg';
console.log('kidGirl444444');
const kidFile = await urlToFile(KidFileUrl);
console.log('kidGirl555555');
const selectFile = ref(womanFile);
const updateFile = () => {
console.log('kidGirl66666');
console.log('state.sexCheckedList[0]', state.sexCheckedList[0]);
console.log('state.ageCheckedList[0]', state.ageCheckedList[0]);
// 业务
// 代码
if (!state.sexCheckedList.length || !state.ageCheckedList.length) return (selectFile.value = womanFile);
if (state.sexCheckedList[0].id === 'Woman' && state.ageCheckedList[0].id === 'Youth') {
selectFile.value = womanFile;
} else if (state.sexCheckedList[0].id === 'KidGirl' && state.ageCheckedList[0].id === 'Infant') {
console.log('kidGirl');
selectFile.value = kidFile;
}
};
const selectFile = ref();
const updateFile = async () => {
selectFile.value = await getDigitModelFile(state.sexCheckedList[0]?.id, state.ageCheckedList[0]?.id);
};
</script>
<template>
<Upload
:file="selectFile"
/>
</template>
思路2:第二种是通过枚举和映射的方式
- 枚举类型定义:定义了 AgeType 枚举,用于表示不同的年龄段。
- 数据结构映射:创建了一个 data 对象,用于映射性别和年龄到图片路径
- 图片获取函数:定义异步函数 getDigitModelFile,根据传入的性别和年龄返回对应的图片文件
(1)枚举类型定义
enum AgeType {
Youth = 'Youth',
YoungAdult = 'YoungAdult',
Adult = 'Adult',
Elderly = 'Elderly',
Infant = 'Infant',
Toddler = 'Toddler',
Child = 'Child',
}
export default AgeType;
sexType同理。
(2)数据结构映射
import AgeType from '../definition/AgeType';
import SexType from '../definition/SexType';
import digit_kidboy_africa from '../../assets/digit_kidboy_africa.png';
......
import { localToFile, urlToFile } from '@software/tools/file';
const data = {
[SexType.Woman]: {
[AgeType.Youth]: digit_kidboy_asia,
},
};
/**
* 返回一个 对应特定性别和年龄的图片
* @param sex
* @param age
* @returns
*/
export const getDigitModelFile = async (sex?: SexType, age?: AgeType): Promise<File> => {
if (!sex || !age) return await localToFile(digit_kidboy_africa);
const path = data?.[sex]?.[age];
return await localToFile(path);
};
(3)使用
这里堆砌的代码就少了很多!
<script setup>
const selectFile = ref();
const updateFile = async () => {
selectFile.value = await getDigitModelFile(state.sexCheckedList[0]?.id, state.ageCheckedList[0]?.id);
};
</script>
<template>
<Upload
:file="selectFile"
/>
</template>
五、用户体验优化
(一) 中间自适应布局,超出的使用scorlloy
- 上方是一个表单名称以及选择框,下方是两个按钮。如果上下也随页面滚动的话,会找不到选择项和按钮,优化体验,应该将上下固定,中间展示区域可以滑动查看。
<style>
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
.header {
height: 60px; /* 固定高度 */
}
.content {
display:flex;
flex: 1;
flex-direction: column;
height: calc(100vh);
overflow: hidden;
.scrollable-content {
flex: 1;
overflow-y: scroll;
}
}
.footer {
height: 60px;
}
</style>
六、写在最后
- 本周感觉稍微好了一丢丢丢,开心哈哈哈但我写的还是好慢呐!
- 现在有点困,but第二篇还没写啊救救我~