本文将深入探讨一系列实用的前端性能优化方案,从基础知识到高级技巧,我们将揭示如何让你的网站在瞬息万变的互联网中脱颖而出,无论你是经验丰富的开发者还是刚入行的新手,这篇文章都将为你提供宝贵的见解和实践建议。
目录
😀首屏与操作速度
🤣时间切片的使用
😀首屏与操作速度
在讲解首屏速度前,我们先分析一下对于前端来讲首屏速度的概念和组成,要知道当用户打开一个界面的时候它的组成部分包括俩方面,如下所示:
白屏时间:屏幕一片空白(请求服务器资源、加载代码)
渲染页面:渲染页面(数据请求以及DOM渲染)
加快首屏速度操作:
1)压缩体积:减少编写代码体积、使用打包工具对代码进行压缩(框架一般都会处理)
2)异步加载:将与首屏加载无关的功能进行异步加载
3)合并接口:对小数据量接口可以合并到其他接口中,减少tcp握手的次数
4)批量渲染:页面包含大量dom可以进行分配随滚动渲染(例如:虚拟列表)
5)用骨架屏:使用骨架屏实现loading效果,先让屏幕不白屏,减少用户焦虑
操作速度:什么情况下会造成操作卡顿和渲染慢呢?一般这种情况基本上是由于下面原因造成的:
1)一次性操作大量dom
2)进行了复杂度很高的运算(常见于循环)
3)vue和react项目中,采用了不必要的渲染
🤣时间切片的使用
如果一个长时间运行的js操作可能会阻塞浏览器的渲染,这样我们页面就看不到反应导致页面长时间处于白屏状态或者页面不展示任何效果,这里我们可以把操作所经历的时间段切成一片一片的,我们可以先操作第一片并把结果交给页面去渲染,页面渲染完成之后再去操作下一片,如下图所示:
接下来我们就开始学习如何对js进行切片操作,这里我们需要用到一个API: requestAnimation。该API函数会在浏览器渲染完成后去执行,所以我们只需要把每个切片放到requestAnimation中,当其执行完一个之后会等着浏览器渲染完再执行下一个,这里通过如下的代码进行示例讲解:
<template><table><thead><td><input type="checkbox" @change="chooseAll">全选</td></thead><tbody><tr v-for="item in dateArr" :key="item.id"><td><input type="checkbox"></td><td>{{ item.name }}</td><td>{{ item.age }}</td><td><span v-if="item.status == 0">状态0</span><span v-if="item.status == 1">状态1</span><span v-if="item.status == 2">状态2</span></td></tr></tbody></table>
</template><script setup>
import { reactive } from 'vue'
let dateArr = reactive([])for(let i = 0; i < 50000; i++){dateArr.push({id: i,name: '张三' + Math.floor(Math.random() * 20),status: Math.floor(Math.random() * 3),checked: false,age: Math.floor(Math.random() * 18)})
}
</script>
通过上面的代码,我们在页面中循环渲染5万条数据,页面刚刷新的时候就会出现卡顿甚至是卡死的现象,网站一直处于刷新的状态中,直到很久页面才会加载出来:
接下来我们开始使用requestAnimationFrame函数先渲染500条数据,500条数据渲染完成之后再继续渲染剩下的数据,数据再悄咪咪的进行渲染,页面也不会有太大的卡顿效果,用户也不会感受到页面的卡顿而且能够及时的查看数据:
<template><table><thead><td><input type="checkbox" @change="chooseAll">全选</td></thead><tbody><tr v-for="item in dateArr" :key="item.id"><td><input type="checkbox"></td><td>{{ item.name }}</td><td>{{ item.age }}</td><td><span v-if="item.status == 0">状态0</span><span v-if="item.status == 1">状态1</span><span v-if="item.status == 2">状态2</span></td></tr></tbody></table>
</template><script setup>
import { reactive } from 'vue'
let dateArr = reactive([])let index = 0
const sliceRender = () => {requestAnimationFrame(() => {let target = index + 500for(; index < target; index++) {dateArr.push({id: index,name: '张三' + Math.floor(Math.random() * 20),status: Math.floor(Math.random() * 3),checked: false,age: Math.floor(Math.random() * 18)})}if (index < 50000) {sliceRender()}})
}
sliceRender()
</script>
从下图我们可以看到数据会随着页面的加载再逐步的进行渲染加载,页面也不会因为一次性加载太多的内容而产生卡顿的效果:
接下来我们再处理一下权限按钮的操作,当数据为5万条的时候我们再去勾选权限的话,页面很可能就会直接卡死,这里我们也是可以借助切片的方式对全选按钮进行操作,具体代码如下所示:
<template><table><thead><td><input type="checkbox" @change="chooseAll">全选</td></thead><tbody><tr v-for="item in dateArr" :key="item.id"><td><input type="checkbox" :checked="checkedList.indexOf(item.id) !== -1" :value="item.id"></td><td>{{ item.name }}</td><td>{{ item.age }}</td><td><span v-if="item.status == 0">状态0</span><span v-if="item.status == 1">状态1</span><span v-if="item.status == 2">状态2</span></td></tr></tbody></table>
</template><script setup>
import { reactive } from 'vue'
let dateArr = reactive([])
let checkedList = reactive([])let index = 0
const sliceRender = () => {requestAnimationFrame(() => {let target = index + 500for(; index < target; index++) {dateArr.push({id: index,name: '张三' + Math.floor(Math.random() * 20),status: Math.floor(Math.random() * 3),checked: false,age: Math.floor(Math.random() * 18)})}if (index < 50000) {sliceRender()}})
}
sliceRender()
const chooseAll = () => {let index = 0const sliceChecked = () => {requestAnimationFrame(() => {let target = index + 500for(; index < target; index++) {checkedList.push(dateArr[index].id)}if (index < dateArr.length) {sliceChecked()}})}sliceChecked()
}
</script>
从下图我们可以看到,当我们勾选全选按钮的时候,全选操作可谓是非常快速了:
其实我们要优化项目不只是去追求绝对的速度提升,我们在无法进一步提升速度的前提下我们可以想办法让体验更好,比如今天说的切片,比如我们对一些操作做异步加载,这些操作对于整体速度都没有提升。但是我们通过合理安排执行顺序,让体验更加好。