关于页面帧数、渲染顺序的问题
import { ref } from 'vue';
// 延时加载js
// 使用方法
// 1、导入import { useDefer } from './defer';
// 2、定义let defer = useDefer(非必填);
// 3、使用<div v-if="defer(10)">数值越大加载顺序越靠后
export function useDefer(maxFrameCount = 1000) {
const frameCount = ref(0);
const refreshFrameCount = () => {
// 核心就是这里,页面每帧执行一次,只有当帧数大于阈值时,才会执行,否则就继续循环
requestAnimationFrame(() => {
frameCount.value++;
if (frameCount.value >= maxFrameCount) {
refreshFrameCount();
}
})
};
refreshFrameCount();
return function (showInFrameCount) {
return frameCount.value >= showInFrameCount;
}
}
requestAnimationFrame
即请求动画帧,它是一个浏览器的宏任务。简单的说,这个api主要是用来做动画的。
css
动画
transition
:过渡动画animation
:直接动画(搭配@keyframes
)js
动画
setInterval
或setTimeout
定时器(比如不停地更改dom元素
的位置,使其运动起来)canvas
动画,搭配js
中的定时器去运动起来(canvas
只是一个画笔,然后我们通过定时器会使用这个画笔去画画-动画)requestAnimationFrame动画(js动画中的较好方案)
这里有一个示例 可以清楚的看出定时器动画和请求帧动画的区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>requestAnimationFrame_yyds</title>
<style>
body {
box-sizing: border-box;
background-color: #ccc;
}
.box1,
.box2 {
position: absolute;
width: 160px;
height: 160px;
line-height: 160px;
text-align: center;
color: #fff;
font-size: 13px;
}
.box1 {
top: 40px;
background: red;
}
.box2 {
top: 210px;
background: green;
}
</style>
</head>
<body>
<button class="btn">👉 let's go!</button>
<div class="box1">定时器动画</div>
<div class="box2">请求动画帧</div>
<script>
// 动画思路:不断修改dom元素的left值,使其运动起来(动画)
let box1 = document.querySelector('.box1')
let box2 = document.querySelector('.box2')
// setInterval定时器方式
function setIntervalFn() {
let timer = null
box1.style.left = '0px'
timer = setInterval(() => {
let leftVal = parseInt(box1.style.left)
if (leftVal >= 720) {
clearInterval(timer)
} else {
box1.style.left = leftVal + 1 + 'px'
}
}, 17)
}
// requestAnimationFrame请求动画帧方式
function requestAnimationFrameFn() {
let timer = null // 可注掉
box2.style.left = '0px'
function callbackFn() {
let leftVal = parseInt(box2.style.left)
if (leftVal >= 720) {
// 不再继续递归调用即可,就不会继续执行了,下面这个加不加都无所谓,因为影响不到
// cancelAnimationFrame取消请求动画帧,用的极少,看下,下文中的回到顶部组件
// 大家会发现并没有使用到这个api(这样写只是和clearInterval做一个对比)
// 毕竟,正常情况下,requestAnimationFrame会自动停下来
cancelAnimationFrame(timer) // 可注掉(很少用到)
} else {
box2.style.left = leftVal + 1 + 'px'
window.requestAnimationFrame(callbackFn)
}
}
window.requestAnimationFrame(callbackFn)
}
// 动画绑定
let btn = document.querySelector('.btn')
btn.addEventListener('click', () => {
setIntervalFn()
requestAnimationFrameFn()
})
</script>
</body>
</html>
$(window).on('scroll', function () {
window.requestAnimationFrame(scrollHandler)
})
平滑滚动到页面顶部
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop
if (c > 0) {
window.requestAnimationFrame(scrollToTop)
window.scrollTo(0, c - c / 8)
}
}
scrollToTop()
大量数据渲染
比如对十万条数据进行渲染,主要由以下几种方法:
使用定时器
//需要插入的容器
let ul = document.getElementById('container')
// 插入十万条数据
let total = 100000
// 一次插入 20 条
let once = 20
//总页数
let page = total / once
//每条记录的索引
let index = 0
//循环加载数据
function loop(curTotal, curIndex) {
if (curTotal <= 0) {
return false
}
//每页多少条
let pageCount = Math.min(curTotal, once)
setTimeout(() => {
for (let i = 0; i < pageCount; i++) {
let li = document.createElement('li')
li.innerText = curIndex + i + ' : ' + ~~(Math.random() * total)
ul.appendChild(li)
}
loop(curTotal - pageCount, curIndex + pageCount)
}, 0)
}
loop(total, index)
使用 requestAnimationFrame
//需要插入的容器
let ul = document.getElementById('container')
// 插入十万条数据
let total = 100000
// 一次插入 20 条
let once = 20
//总页数
let page = total / once
//每条记录的索引
let index = 0
//循环加载数据
function loop(curTotal, curIndex) {
if (curTotal <= 0) {
return false
}
//每页多少条
let pageCount = Math.min(curTotal, once)
window.requestAnimationFrame(function () {
for (let i = 0; i < pageCount; i++) {
let li = document.createElement('li')
li.innerText = curIndex + i + ' : ' + ~~(Math.random() * total)
ul.appendChild(li)
}
loop(curTotal - pageCount, curIndex + pageCount)
})
}
loop(total, index)
监控卡顿方法
每秒中计算一次网页的 FPS,获得一列数据,然后分析。通俗地解释就是,通过 requestAnimationFrame API 来定时执行一些 JS 代码,如果浏览器卡顿,无法很好地保证渲染的频率,1s 中 无法达到 60 帧,即可间接地反映浏览器的渲染帧率。
var lastTime = performance.now()
var frame = 0
var lastFameTime = performance.now()
var loop = function (time) {
var now = performance.now()
var fs = now - lastFameTime
lastFameTime = now
var fps = Math.round(1000 / fs)
frame++
if (now > 1000 + lastTime) {
var fps = Math.round((frame * 1000) / (now - lastTime))
frame = 0
lastTime = now
}
window.requestAnimationFrame(loop)
}
我们可以定义一些边界值,比如连续出现 3 个低于 20 的 FPS 即可认为网页存在卡顿。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- igbc.cn 版权所有 湘ICP备2023023988号-5
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务