这里只谈前端针对用户感受的优化体验
优化执行层代码逻辑
- 检查代码是否有多余的接口调用,导致冗余
问题CASE:
- watch监听多次调用导致同样的代码被执行多次
- 错误的执行顺序,导致两个函数的执行区域存在重叠
解决方案:
- 代码层面的时序逻辑更改重构。这个需要结合实际的情况变化,比如频繁切换样式变更DOM行为。
- 防抖和节流。一个函数有概率短期内执行多次,比如点击button,点击新增文件夹,点击弹窗,输入框输入查询,这种情况都可以使用防抖节流去优化整个体验感受。
- 监听器+定时器及时解绑,不然全局绑定的监听器/定时器在页面销毁后还在进行浏览器内存和线程消耗
- 在spa项目中router导航的时候,可以keep-alive,并且设置最多缓存的页面,这样既可以防止组件缓存,防止太多页面缓存在后台占据内存,有些高性能消耗的工作,也可以在后台的时候先关闭,等到用户再切换回前台的时候再去开启,比如轮询排查版本号是否发生打包更新,在页面切到后台的时候就可以把轮询定时器暂停,等到切换回前端页面的时候再去开启
- shallowRef/shallowReactive减少性能损耗,如果数据无需深层响应式的时候可以使用
- 利用缓存优化重复的数据,比如前端缓存数据,这个数据特定形况下不会变,如果不变的话则走前端缓存,如果变化则再调后端接口数据
- 长列表优化:只加载可视区域往外大概一个屏幕的数据,等到下拉的时候再去调后端的接口进行数据的拼接
虽然vue还有自封装的v-once/v-memo等指令工具,但是因为vue本身是细粒度的响应式检测,所以v-memo等指令实际上并没有很频繁使用的场景(也可能我没遇到那种高性能多页面加载的极端case); react里面的useMemo和useCallback,React.memo等则很必要,因为react是以一个模块为单位的
骨架屏&Loading优化白屏加载体验
- Loading一般组件库都会有自带的组件
- 骨架屏我用的是vue-content-loader去处理局部组件骨架屏,不过这个是需要自己去绘制骨架屏,优点是自由度高,但是相对比较繁琐;vite-plugin-vue-skeleton据说可以自动生成首页骨架屏,但是公司镜像没有,导致没办法尝试一下
- errorboundary + suspense + fallback
//主文件,子文件HeavyComponent只要正常执行接口代码就可以
<template>
<div>
<ErrorBoundary>
<Suspense>
<!-- default 插槽:要等待的异步内容 -->
<template #default>
<HeavyComponent />
</template>
<!-- fallback 插槽:加载中兜底内容 -->
<template #fallback>
<div>加载中...</div>
</template>
</Suspense>
</ErrorBoundary>
<div>
</template>
<script>
import { defineAsyncComponent } from 'vue';
const HeavyComponent = defineAsyncComponent(() =>
import('./components/HeavyComponent.vue')
);
</script>
error-boundary的组件vue没有,需要自己实现对应的代码,主要依托于vue的生命周期中的onErrorCaptured函数,具体代码实现Demo如下:
<template>
<div>
<div v-if="hasError">
<div></div>
</div>
<slot v-if="!hasError" />
</div>
</template>
<script setup>
import { ref, onErrorCaptured } from 'vue';
const hasError = ref(false);
onErrorCaptured((err) => {
console.log(`出现错误了!`);
hasError.value = true;
console.error(`err:`, err);
return true;
});
</script>