项目中的一些需求条件与出现的bug情况:
1、在一个查询页中,选择列表中的一项点击预订按钮跳转到预订页(此处列表项没有id值,预定页的tagView标题要自定义内容展示,所以我是用(自定义内容拼接随机数)作为唯一标识,通过query传参 ,可以创建多个不同的预订页面进行相应操作),预定页面的渲染数据是通过查询页的路由state传参,跳转后的页面是使用history.state.data来接收传递过来的数据做渲染
2、问题复现:在当前订单页点击标签页的刷新功能(刷新页面),会出现新创建的一个订单页,并且原来的订单页的数据会消失(大致猜测是页面刷新,路由传递的参数没传递正确,导致刷新后,没有query参数,就会创建一个新的独立的页面出来)
知道大致问题原因后,先去看了一下标签页的刷新函数
//原标签页的刷新功能
function refreshSelectedTag(view: TagView) {
tagsViewStore.delCachedView(view);
const { fullPath } = view;
console.log(fullPath, "fullPath");
nextTick(() => {
router.replace({ path: "/redirect" + fullPath});
});
}
//代码更改后:
function refreshSelectedTag(view: TagView) {
tagsViewStore.delCachedView(view);
const { fullPath } = view;
console.log(fullPath, "fullPath");
nextTick(() => {
const currentRoute = router.currentRoute.value;
const { path, query } = currentRoute;
// 尝试在刷新订单页的逻辑中,将之前的路由参数重新传递给新的订单页,以确保新建的订单页能够正确显示之
// 前的订单信息,(自我觉得:只要tag标签的内容一样就不会产生新的订单页了)
router.replace({ path: "/redirect" + fullPath, query });
});
}
新创订单页的bug解决了,但是刷新后,参数消失还没有解决。此时有个思路就是把数据存储到前端数据库中,若是刷新页面后没有数据,就从数据库中通过主键keyPath:id查询出来并渲染。id我用的是跳转时的query参数(就算页面刷新,参数也不会消失),确保id要与query参数一致,以下是我使用indexedDB的代码
==========================查询页 跳转===========================
import { openDB } from "@/utils";
import { useRouter } from "vue-router";
const router = useRouter();
//跳转预定页
const toBooking = async (item: any, index: number) => {
if (radioValue.value.name === "") {
return ElMessage.info("请先选择舱位");
} else if (index !== radioValue.value.index1) {
return ElMessage.info("请先选择价格后在预定");
}
const data = {
...item,
price: radioValue.value,
cabin_type: cabin_type.value,
work_no: work_no.value,
};
// tagTitle 唯一标识
const tagTitle = `${dayjs.unix(item.fly_day).format("YYYY-MM-DD")} ${
item.voyage
} ${item.flight} ${Math.floor(Math.random() * 10000)}` as string;
// 存数据库的对象
const obj = {
id: tagTitle,
info: JSON.stringify(data),
status: false,
};
//添加数据到库中
addTask(obj);
router.push({
name: "BookingEdit",
query: {
title: tagTitle,
},
state: { data: JSON.stringify(data) }, //使用state传参,可以传对象(不会显示到url上)
});
};
let dbName = "order"; //定义数据库名
let version = 1; //版本号
let db: any; //数据库对象
//添加数据
function addTask(data: any) {
let request = db
.transaction("Today_Mission", "readwrite")
.objectStore("Today_Mission")
.add(data);
request.onsuccess = (event: any) => {
console.log("添加数据库成功");
};
request.onerror = (event: any) => {
console.log("添加数据库失败");
};
}
//缓存组件的两个钩子函数
onDeactivated(() => {
clearInterval(timeId);
});
onActivated(async () => {
db = await openDB(dbName, version); //打开数据库
});
===================================查询页============================================
==================================utils文件封装打开数据库的方法========================
//创建数据库
export const openDB = (dbName: any, version = 1) => {
return new Promise((resolve, reject) => {
//兼容浏览器
var indexedDB = window.indexedDB;
let db;
//打开数据库,若没有就会创建
const request = indexedDB.open(dbName, version);
//数据库打开成功回调
request.onsuccess = function (event: any) {
db = event.target.result; //数据库对象
console.log("数据库打开成功", db);
resolve(db);
};
//数据库打开失败的回调
request.onerror = function (event) {
console.log("数据库打开报错");
};
//数据库有更新时候的回调
request.onupgradeneeded = function (event: any) {
console.log("数据库更新");
db = event.target.result; //数据库对象
var objectStore;
//创建存储库
objectStore = db.createObjectStore("Today_Mission", { keyPath: "id" });
// 建立索引,info可能重复,因此unique设置为false
objectStore.createIndex("info", "info", { unique: false });
};
});
};
=======================================utils文件======================================
=====================================预定页 接收参数===================================
import { openDB } from "@/utils";
import { useRoute } from "vue-router";
let db: any;
let dbName = "order";
let storeName = "Today_Mission";
let version = 1;
//读取数据库数据函数 此函数会返回一个结果resolve()
function getDataByKey(db: any, storeName: string, key: string) {
return new Promise((resolve, reject) => {
var transaction = db.transaction([storeName]); // 事务
var objectStore = transaction.objectStore(storeName); // 仓库对象
var request = objectStore.get(key); // 通过主键获取数据
request.onerror = function (event: any) {
console.log("事务失败");
};
request.onsuccess = function (event: any) {
console.log("主键查询结果: ", request.result);
resolve(request.result);
};
});
}
//组件是被缓存了,所以用onActivated
onActivated(async () => {
db = await openDB(dbName, version);
console.log(route.query.title, "route");
if (history.state.data) {
...同理处理数据
} else {
//刷新页面的话,就从数据库里找到这项数据渲染
const data = (await getDataByKey(
db,
storeName,
route.query.title as any
)) as any;
info.value = JSON.parse(data.Task);
AmountInfoRef.value.setData(info.value);
AmountInfoRef.value.form.seat_type = info.value.cabin_type;
flightRef.value.setInfo(info.value);
}
});
=======================================预定页========================================
最后一步,清空数据库数据
=======================================登录页========================================
//清空数据库操作
function clearDatabase() {
const request = indexedDB.open("order", 1);
request.onsuccess = function (event: any) {
const db = event.target.result;
const transaction = db.transaction("Today_Mission", "readwrite");
const objectStore = transaction.objectStore("Today_Mission");
const clearRequest = objectStore.clear();
clearRequest.onsuccess = function () {
console.log("数据库清空成功");
};
clearRequest.onerror = function (event: any) {
console.error("数据库清空失败", event.target.error);
};
};
}
//登录成功就清空一遍数据库数据(防止数据过多,发生一些冲突或并发问题
=====================================================================================
以上代码能解决我目前发生的问题,在此记录一下。若代码有什么问题,欢迎指出来,改正。