优化
刀刀
12/31/2024
0 字
0 分钟
在项目中,优化也是一个不可或缺的环节,在业务中,我涉及到的优化有以下几点:
- 代码优化:通过引入第三方库或方法实现同样的功能,代码量更少,易读性更好
- 性能优化:通过引入第三方库等方法实现地图渲染加载速度优化
- 体验优化:通过引入第三方库等方法实现用户体验优化
关于优化,在项目中我涉及到的分别有以下几点。
性能优化
数据抽稀
有一个图层需求是渲染地图面,UI效果如下所示:
根据地图官网可以使用 Polygon
方法渲染面。不过由于后端返回的数据量过于庞大,因此在渲染的时候耗时很长,长达半分钟左右才能加载完毕。
这显然是不合理的,因此需要做点优化。在搜索时,发现有一个集成库 Turf.js
用于处理地图数据,其中它有一个 simplify
方法可以简化数据。官网指路:简化多边形 | Turf.js中文网 (fenxianglu.cn) 。
根据官方文档指示,需要先使用库的 polygon
方法获取需要的数据。该方法传入一个首尾相同数据的三维数组。然后设置抽稀程度、是否允许修改等参数。最后调用 simplify
方法获取到抽稀后的简化版本。
抽稀函数封装如下所示:
// 抽稀
export const lessDataFn = arr => {
// 首尾相同
arr.forEach(item => item.push(item[0]));
const option = {tolerance: 0.009, highQuality: false, mutate: true};
const newArr = arr.map(p => {
// 如果当前数据长度大于4,则抽稀
if (p.length >= 4) {
const arrHandle = simplify(polygon([p]), option);
return arrHandle.geometry.coordinates[0];
}
return p;
});
return newArr;
};
接口请求次数
由于数据量过于庞大,后端接口请求速度也会有所变慢,如果网络环境稍差,还会请求失败。此处也可以做一个缓存优化。
一般情况下提到缓存,都会想到浏览器缓存 localStorage
,不过数据量庞大浏览器缓存也未必能够存的下,因此这里可以通过 new Map
缓存到内存中。
如果 new Map().has()
能够拿到数据,说明之前已经调用过接口获取数据并保存,此时直接获取数据即可,不再需要调接口;反之才需要调用接口获取数据并保存。
代码如下所示:
const polygonDataMap = new Map();
export const setArea = async payload => {
if (polygonDataMap.has(payload.areaName + '-search')) {
xxx.value = polygonDataMap.get(payload.areaName + '-search');
return;
}
const {data} = await yyy(payload);
districtPolygonList.value = data;
polygonDataMap.set(payload.areaName + '-search', districtPolygonList.value);
};
保存后运行,可以发现后续页面渲染速度变快很多。
细粒度追踪响应式数据变化
地图产生的相关元素变量,在保存成响应式时,不使用 ref
保存,而是用 shallowRef
。
在 Vue 3 中,shallowRef
替换掉 ref
的优化是对响应式数据进行更加细粒度的追踪,从而提高性能的优化。
在 Vue 2 中,ref
的实现方式是双向绑定,即当数据变化时,会触发更新视图的操作。然而,这种实现方式有一个缺点:它会追踪整个对象或数组的变化,即使只有其中一个属性发生了变化,也会重新渲染整个对象或数组。这样就会导致性能问题,特别是在处理大型对象或数组时。
Vue 3 中引入了 shallowRef
,它通过使用 Proxy
对象来实现,可以进行比较精细的响应式追踪。与 ref 不同的是,shallowRef
只会追踪对象或数组的第一层属性,当第一层属性发生变化时,才会触发更新视图的操作。这样就可以避免不必要的重新渲染,提高性能。
适用场景:
- 当需要追踪一个简单对象或数组的变化时,可以使用
shallowRef
。 - 当需要追踪一个复杂对象或数组的变化时,可以使用
reactive
或ref
来实现深层次的响应式追踪。
体验优化
Animate.css
在项目中,会需要实现一些交互效果,如打开关闭弹窗、鼠标悬停等等,只是简单的 v-show
、v-if
或样式 display
、:hover
自然可以实现功能,但是显得有点单调。如果加上动画效果会给用户更好的体验。
但是纯手写动画效果会消耗一定的时间,前期开发是以效果为主,用时间在动画上显得本末倒置,因此可以使用第三方库 Animate.css
来实现动画效果。官网指路:动画 .css |CSS 动画的跨浏览器库。 (animate.style)
使用流程如下:
安装依赖
npm 安装
shellnpm install animate.css --save
shellyarn add animate.css
shellpnpm install animate.css --save
cdn 安装
html<head> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.0.0/animate.min.css" /> </head>
引入使用
jsimport 'animate.css'
html<h1 class="animate__animated animate__fadeIn">An animated element</h1>
使用时需要加上
animate__animated
类名,然后animate__
动画类名前缀加动画名称fadeIn
,就能实现效果。自定义修改动画属性
直接修改
style
css/* 只更改一个动画的持续时间 */ .animate__animated.animate__bounce { --animate-duration: 2s; } /* 更改所有动画的持续时间 */ :root { --animate-duration: 800ms; --animate-delay: 0.9s; }
特殊类名修改
html<div class="animate__animated animate__bounce animate__delay-2s">Example</div>
接口调用调整
在微观二维的场景下,用户可以通过点击类型筛选按钮筛选结构物,在之前的做法是点击后调用接口获取新的数据,把扎点清空后重新渲染。
后续产品提出清空后渲染不利于用户体验,需要改进。
修改后的逻辑为在最开始统一获取全部的数据,通过 filter
依次保存,后续用户点击时通过 v-if
显隐对应的扎点即可。