背景
背景
最近在对公司node+jquery
捞系统基层进行版本升级,使用最新技术栈vue + ts + vite + pinia
,对于捞系统原有页面将会进行iframe
不会再其基础上进行修改,大大减少了维护成本,但是由于其页面较多,且页面之间存在关联,所以需要对页面进行缓存,避免重复加载,提升用户体验,其中也遇到了一系列兼容问题,总结如下:
对于系统升级,当然要使用最新技术栈了,这样公司使用的技术栈就会统一,也不会因为技术栈不统一导致个人成长缓慢;对于相对系列问题也可以进行小组探讨;
从计划开始部署到真正上手改造花费将近一周时间,底层框架结构采用vue
,里层内容采用iframe
链接老项目页面;
Start
开始进行对系统技术的升级,大致升级的范围:
- 登录,重置密码重构,摒弃原来
jquery
页面 - 路由,权限的重置,需要后端开发人员配合,现在市面上的中后台系统的路由和权限基本都是后端来管理,很少使用前端路由
- 基础库,方法的编写,对于常用的方法,
hooks
需要统一封装管理 - 常用枚举的封装,接口定义,类型定义
- 请求拦截,相应的封装;
环境的配置
当然对于企业项目,多环境已经是常见的,开发环境,测试环境,预发布环境,线上环境等等;对于这些环境一些请求的域名,配置参数当然也是不一样的,这时候就可以在.env
文件中配置,大概配置项如下:
sh
VITE_APP_API_URL='http://www.wangxiaoze.wang'
VITE_APP_API_KEY='abc'
VITE_APP_APP_ID='123456'
# 当然对于iframe页面需要相对环境的域名配置
VITE_APP_IFRAME_HOST='http://www.wangxiaoze.wang'
utils, hooks 等基础配置的封装
utils
基础的方法,正则的封装等等;hooks
的封装,对于一些常用的方法,比如loading
,message
,dialog
,confirm
,loading
等方法,需要统一封装管理;config
对一些系统级的配置项,如:七牛的配置,标题,logo 的配置等等store-pinia
的配置axios
的封装,对于请求的拦截,响应的封装,请求的封装等等api
的封装,对于一些接口的封装,如:七牛的图片上传,七牛的图片删除,七牛的图片列表等等
axios, api 的封装
对于axios
的使用,代码如下:
typescript
const instance: AxiosInstance = axios.create({
baseURL: `${import.meta.env.VITE_APP_BASE_URL}`,
timeout: 60000,
});
// 请求拦截器
instance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
// 根据自己的需要进行修改
return config;
},
error => error
);
// 响应拦截器
instance.interceptors.response.use(
(response: AxiosResponse) => {
// 根据自己的需要进行修改
return response.data;
},
error => {
return Promise.reject(error.response);
}
);
interface IHttpResult<T> {
code: number;
message: string;
data: T;
success: boolean;
}
// 泛型T: 返回接口字段类型 泛型U: 是参数的数据类型
const httpServer = {
get<T = any, U = any>(url: string, params: U): Promise<IHttpResult<T>> {
return instance.request(getParamsConfig(url, "get", params));
},
post<T = any, U = any>(url: string, params: U): Promise<IHttpResult<T>> {
return instance.request(getParamsConfig(url, "post", params));
},
put<T = any, U = any>(url: string, params: U): Promise<IHttpResult<T>> {
return instance.request(getParamsConfig(url, "put", params));
},
delete<T = any, U = any>(url: string, params: U): Promise<IHttpResult<T>> {
return instance.request(getParamsConfig(url, "delete", params));
},
postForQuery<T = any, U = any>(
url: string,
params: U
): Promise<IHttpResult<T>> {
return instance.request(
getParamsConfig(
url,
"post",
qs.stringify(params, {
arrayFormat: "repeat",
})
)
);
},
};
export { instance as axios, httpServer };
系统采用的是ts
,那么对于api
的管理使用枚举整理,相关api
的配置如下:
typescript
enum UsetApi {
// 七牛图片上传
UploadImage = "/api/upload/image",
// 七牛图片删除
DeleteImage = "/api/upload/delete",
// 七牛图片列表
ImageList = "/api/upload/list",
}
import { httpServer } from "@/http";
export function getList<T, U>(data: U) {
return httpServer.get<T>(UsetApi.ImageList, data);
}
iframe 内嵌页面缓存
刚开始使用iframe
会发现一个问题,就是iframe
内嵌页面刷新后,iframe
会重新加载,导致页面会重新刷新,iframe 资源也会重新加载,会造成性能影响 那么如何解决呢?
- 使用
v-show
这样就可以避免刷新资源的问题 - 定位将 iframe 页面定位可视区域之外;
vue
<iframe
v-for="item in routes"
:key="item.path"
v-show="item.path === route.path"
/>
虽然发现不会再次请求资源,刷新页面,但是会发现一个细节问题,那就是滚动条不会定位到上次的位置,这样用户频繁跳转页面,滚动条不会定位,会造成一定的使用不便;
另外的一中方案可以解决此类问题;
老系统的预览图片,打开标签页兼容
捞系统的预览图片会打开新的标签页,但是新系统要使用element-plus
的预览图片的样式,当然打开标签页也是同样问题;
想要同时解决新老系统的兼容问题,那么可以参考一下方案:
js
// 老系统
window.parent.postMessage(
{
command: "open",
data: {
url: url,
},
},
"*"
);
// 新系统
window.addEventListener("message", function (e) {
if (e.data.command === "open") {
// 根据自己的情况操作逻辑
// 判断是否是当前页面打开
}
});
// 移除,避免叠加
window.removeEventListener("message", function (e) {
if (e.data.command === "open") {
// 根据自己的情况操作逻辑
// 判断是否是当前页面打开
}
});
当然图片或者其他也是类似操作;