之前做考科目一和科目四
大部分驾考软件免费的功能都是全部题目,2000道题人都做麻了
然后其他很大一部分功能:技巧讲解,精选500题,考前秘卷,真实考场模拟等功能都是收费的
就自己开发一个驾考wx小程序:愿兽驾道
核心技术点:
1.swiper无限滚动实现
问题
对于题目页面左右滑动功能,我做了很多的尝试,目前来说我论坛上常用的解决方式是只展示5张或10张图片,为啥?
因为会有1000-2000个题目展示,导致内存泄漏,页面直接卡死
但是这种方式有一个弊端,就是会出现卡顿的情况,因为每次更换,相当于重新渲染好几张图片,但是滑动的时候有卡顿,整个尤其是在老机型上尤为明显
实现方式
采用无限滚动方式:
使用原生的swiper组件,因为原生的swiper开启循环后,会自动到第一张实现循环,那么我们只需要按照算法,对接即可实现无缝的无限循环
例如:
当角标到达0时,备注组是:0.1.2
左滑动,预备组就变成了1,2,3
右滑动,预备组 就变成了3,0,1
只要保证每次滑动的时候,展示位置为中间位置,就可以实现,展示3个页面的同时,实现页面不卡顿,也就是无缝
我还顺便封装了一个组件,大家可以参考使用
<template>
<view>
<swiper circular :style="{height:props.height+'px'}" :current="showIndex"
@change="scrollIssure">
<swiper-item :item-id="index+''" v-for="(item,index) in showList" :key="index">
<slot :item="item" :index="index">
<!-- 默认内容,如果父组件没有提供插槽内容则显示 -->
<text>{{ index + 1 }}.{item}</text>
</slot>
</swiper-item>
</swiper>
</view>
</template>
<script setup>
import {
nextTick,
onMounted,
ref,
defineProps,
watch
} from 'vue'
const props = defineProps({
current: {
type: Number,
default: 0
},
height: {
type: Number,
default: 300
},
list: {
type: Array,
default: () => []
}
})
watch(() => props.list, (newList) => {
nextTick(() => {
scrollIssure({
"detail": {
"current": showIndex.value
}
});
})
})
watch(() => props.current, (index) => {
if (initCurrent.value === index) {
return;
}
if (index % 3 === 0) {
showIndex.value = 0;
beforeShowIndex.value = 0
}
if (index % 3 === 1) {
showIndex.value = 1;
beforeShowIndex.value = 1
}
if (index % 3 === 2) {
showIndex.value = 2;
beforeShowIndex.value = 2
}
initCurrent.value = index;
nextTick(() => {
scrollIssure({
"detail": {
"current": showIndex.value
}
});
})
})
const initCurrent = ref(0);
const showList = ref([]);
const beforeShowIndex = ref(1);
const showIndex = ref(1);
const emit = defineEmits(['update:current']);
const updateCurrent = (index) => {
emit('update:current', index); // 通知父组件更新
};
onMounted(() => {
initCurrent.value = props.current;
})
const scrollIssure = (e) => {
let toIndex = e.detail.current;
showIndex.value = toIndex;
if (props.list.length < 3) {
return;
}
//需要记录前上一次位置判断向后或向前滑动
let speed = toIndex - beforeShowIndex.value;
beforeShowIndex.value = toIndex;
if (speed === 1 || speed === -2) { //向前
let changeCurrent=calculateIndex(initCurrent.value,true);
initCurrent.value=changeCurrent;
updateCurrent(changeCurrent)
} else if (speed === -1 || speed === 2) { //向后
let changeCurrent=calculateIndex(initCurrent.value,false);
initCurrent.value=changeCurrent;
updateCurrent(changeCurrent)
}
//获取当前位置为核心不变,渲染页面,前后位置页面
//有三种占位情况
let beforeIndex=calculateIndex(initCurrent.value,false);
let afterIndex=calculateIndex(initCurrent.value,true);
switch (toIndex) {
case 0:
if (speed === 0) {
showList.value[0] = props.list[initCurrent.value];
}
showList.value[1] = props.list[afterIndex];
showList.value[2] = props.list[beforeIndex];
break;
case 1:
if (speed === 0) {
showList.value[1] = props.list[initCurrent.value];
}
showList.value[0] = props.list[beforeIndex];
showList.value[2] = props.list[afterIndex];
break;
case 2:
if (speed === 0) {
showList.value[2] = props.list[initCurrent.value];
}
showList.value[0] = props.list[afterIndex];
showList.value[1] = props.list[beforeIndex];
break;
}
}
const calculateIndex=(index,add)=>{
if(add){
return index+1>props.list.length-1?0:index+1
}
return index-1<=0?props.list.length-1:index-1
}
</script>
<style>
</style>
组件是可以直接使用的,注意下传参即可
2.题库的mysql数据库结构设计
问题
有人可能会说,数据库还要设计啥,当然简单的题库可能只需要记录题目即可,但是复杂的题库,需要很多功能的记录,比如说不同车型,科目题目如何记录,车型目前有10多种:包括小车,客车,货车,摩托车,无人机等等,科目四个,两者一合,会出来100来条模块题库,这还只是全部题库的情况下,加上分类,甚至能上到1000多条
然后1000多条数据每个里面又会有不同得题目,相互交融,结合起来还是比较复杂
方案
使用中间模块表,直接记录该模块下题目全部的id,那么就不用每次去题库一一查询,只需要提前跑一遍脚本,分好类,不然io大的吓人,同时加上redis的话,基本就解决了
页面的话我就不贴了,大家按需参考:wx搜:愿兽驾道