添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

一、数据过多 导致页面卡顿

  1. 采用懒加载+分页(前端维护懒加载的数据分发和分页)
    类似于表格的分页功能,具体思路就是用户每次只加载能看见的数据,当滚动到底部时再去加载下一页的数据。
  2. 使用虚拟滚动技术 (目前react的antd4.0已支持虚拟滚动的select长列表)
    React官网推荐我们使用 react-window react-virtualized 这2个热门的虚拟滚动库。它们提供了多种可复用的组件,用于展示列表、网格和表格数据。

  3. (1). 用ajax获取到需要处理的数据, 共13万条
    (2). 将数组分组,每组500条,一共260组
    (3). 循环这260组数据,分别处理每一组数据, 利用setTimeout函数开启一个新的执行线程(异步),防止主线程因渲染大量数据导致阻塞。

---------------------------------------------------------------------------------------------------------------------------------

懒加载 + 分页方案

懒加载的实现主要是通过监听窗口的滚动,当某一个占位元素可见之后去加载下一个数据。

通过监听 window 的 scroll事件,以及对 poll元素 使用 getBoundingClientRect 来获取 poll元素相对于可视窗口的距离,从而实现一个懒加载方案。其中 prevY 存储的是窗口上一次滚动的距离,只有在向下滚动并且滚动高度大于上一次时才更新其值。

getBoundingClientRect()方法:用于获取某个元素相对于视窗的位置集合。
集合中有 top, right, bottom, left 等属性。

function scrollAndLoading() {
    if(window.scrollY > prevY) {  // 判断用户是否向下滚动
      prevY = window.scrollY
      if(poll.current.getBoundingClientRect().top <= window.innerHeight) {
        // 请求下一页数据
useEffect(() => {
    // something code
    const getData = debounce(scrollAndLoading, 300)
    window.addEventListener('scroll', getData, false)
    return () => {
      window.removeEventListener('scroll', getData, false)
  }, [])

分页方案:定义 curPage:当前的页数、pageSize:每一页展示的数量、data:传入的数据量。

let data = [];
let curPage = 1;
let pageSize = 16;
let prevY = 0;
// other code...
function scrollAndLoading() {
    if(window.scrollY > prevY) {  // 判断用户是否向下滚动
      prevY = window.scrollY
      if(poll.current.getBoundingClientRect().top <= window.innerHeight) {
        curPage++
        setList(searchData.slice(0, pageSize * curPage))

数据分组并利用 setTimeout:通过取余数将数据分组,然后把数据一段一段的显示到页面,

var Search = {  //列表数据搜索
  data() {
    return {
      serarchWord: '',
      listData: [],
  methods: {
    // 获取数据
    getData() {
      axios({
        url: 'http://apicloud.mypaas.com.cn/mockview/appdesign?path=%2Fapi%2Flistdata&api=%2Fapi%2Flistdata',
        method: 'GET',
        params: {
          keyWord: this.serarchWord
      }).then(res => {
        // this.listData = res.data.data
        let data = res.data.data
        let groupData = this.group(data)
        for (let i = 0; i < groupData.length; i++) {
          setTimeout(() => {
            this.listData.push(...groupData[i])
          }, 1000 * i);
    group(data) {  //对数据进行分组
      var result = [];
      var groupItem;
      for (var i = 0; i < data.length; i++) {
        if (i % 1000 == 0) {
          groupItem != null && result.push(groupItem);
          groupItem = [];
        groupItem.push(data[i]);
      result.push(groupItem);
      return result;
    inputChange() {
      this.debounceSearch()
    debounce(fn, wait) {  //防抖
      var timeout = null;
      return function () {
        if (timeout !== null)
          clearTimeout(timeout);
        timeout = setTimeout(fn, wait);
  mounted() {
    this.debounceSearch = this.debounce(this.getData, 800)

二、DOM操作造成的页面卡顿问题及解决

1.合并多次的DOM操作为单次的DOM操作

2.把DOM元素离线或隐藏后修改适合那些需要大批量修改DOM元素的情况

这样只会在DOM元素脱离和添加 or 隐藏和显示 时,才会造成页面的重绘或回流,对脱离了页面布局流的DOM元素操作就不会导致页面的性能问题。具体的方式主要有三种:

(1)将频繁的操作改为一次性操作,使用文档片段 :document.createDocumentFragment() 

       创建一个文档片段,并在此片段上进行必要的DOM操作,操作完成后将它附加在页面中。对页面性能的影响只存在于最后把文档片段附加到页面的这一步操作上。

       因为文档片段存在于内存中,并不在DOM树中,所以将子元素插入到文档片段时不会引起页面回流(对元素位置和几何上的计算)。因此,使用文档片段通常会带来更好的性能。

//频繁操作
const list = document.getElementById('list')
for (let i = 0; i < 10; i++) {
    const li = document.createElement('li')
    li.innerHTML = `List item ${i}`
    list.appendChild(li) //插入 10 次
// ------------------------------------------
//通过创建一个新的空白的文档片段( DocumentFragment),最后一次插入
const list = document.getElementById('list')
const frag = document.createDocumentFragment()  //关键语句
for (let i = 0; i < 10; i++) { 
    const li = document.createElement('li') 
    li.innerHTML = `List item ${i}`
    frag.appendChild(li) //插入 10 次
//都完成后,再传DOM树中
list.appendChild(frag)

(2)通过设置DOM元素的 display: none 来隐藏元素

       通过隐藏页面的DOM元素,达到在页面中移除元素的效果,经过大量的DOM操作后恢复元素原来的display样式。

var myElement = document.getElementById('myElement');
myElement.style.display = 'none';
// 一些基于myElement的大量DOM操作
myElement.style.display = 'block';

(3)克隆DOM元素到内存中

       把页面上的DOM元素克隆一份到内存中,然后再在内存中操作克隆的元素,操作完成后使用此克隆元素替换页面中原来的DOM元素。这样一来,影响性能的操作就只是最后替换元素的这一步操作了,在内存中操作克隆元素不会引起页面上的性能损耗。

var old = document.getElementById('myElement');
var clone = old.cloneNode(true);
// 一些基于clone的大量DOM操作
old.parentNode.replaceChild(clone, old);

3. 设置具有动画效果的DOM元素的position属性为fixed或absolute(提高动画效果的展示性能)

       把页面中具有动画效果的元素设置为绝对定位,使得元素脱离页面布局流,从而避免了页面频繁的回流,只涉及动画元素自身的回流了。

4. 对DOM查询做缓存

for (let i = 0; i < document.getElementsByTagName('p').length; i++) {
   //每次循环,都会计算length,频繁进行DOM操作
//------------------------------------------
//缓存 DOM 查询结果
const pList = document.getElementsByTagName('p')
const length = pList.length
 for (let i = 0; i < length; i++) {
   //缓存length,只进行一次DOM查询

5. 使用 事件代理/委托 方式绑定事件

       利用事件冒泡机制,只在父元素上绑定事件处理,用于处理所有子元素的事件,这样就不需要给每个子元素都绑定事件。

// 获取父节点,并添加一个click事件
document.getElementById('list').addEventListener("click",function(e) { 
    if(e.target && e.target.nodeName.toUpperCase == "LI") {
    // 针对子元素的处理

三、请求突增导致页面崩溃

1、开启CDN加速(服务器配置完全充足,但是网站访问速度明显变慢了)
       把源站内容分发至各地最接近用户的节点;缩短用户到节点的物理距离,使用户可就近取得所需内容,降低延迟。简单来说,当一个网站开启了CDN加速,能给用户的感觉是访问网站速度或者下载东西的速度会明显比没有开启加速更快了。

       高防CDN可以自动识别恶意攻击流量,对这些虚假流量进行智能清洗,将正常访客流量回源到源服务器IP上,保障源服务器的正常稳定运行。

2、确认服务器硬件是否足够支持当前的流量。(服务器配置明显不够用,导致宕机或者访问出现错误。)

      进行服务器扩容:配置一台更高性能的专用服务器。

3、优化数据库访问。

       服务器的负载过大,一个重要的原因是CPU负荷过大,降低服务器CPU的负荷,才能够有效打破瓶颈。而使用静态页面可以使得CPU的负荷最小化。前台实现完全的静态化当然最好,可以完全不用访问数据库,不过对于频繁更新的网站,静态化往往不能满足某些功能。

       缓存技术就是另一个解决方案,就是将动态数据存储到缓存文件中,动态网页直接调用这些文件,而不必再访问数据库,WordPress和Z-Blog都大量使用这种缓存技术。

       如果确实无法避免对数据库的访问,那么可以尝试优化数据库的查询SQL,避免使用 Select * from 这样的语句,每次查询只返回自己需要的结果,避免短时间内的大量SQL查询。

4、禁止外部的盗链。

       外部网站的图片或者文件盗链往往会带来大量的负载压力,因此应该严格限制外部对于自身的图片或者文件盗链,目前可以简单地通过refer来控制盗链,Apache自己就可以通过配置来禁止盗链,IIS也有一些第三方的ISAPI可以实现同样的功能。当然,伪造refer也可以通过代码来实现盗链, 不过目前蓄意伪造refer盗链的还不多,可以先不去考虑,或者使用非技术手段来解决,比如在图片上增加水印。

5、控制大文件的下载。

       大文件的下载会占用很大的流量,并且对于非SCSI硬盘来说,大量文件下载会消耗CPU,使得网站响应能力下降。因此,尽量不要提供超过2M的大文件下载, 如果需要提供,建议将大文件放在另外一台服务器上。

6、使用不同服务器分流主要流量

      将文件放在不同的主机上,提供不同的镜像供用户下载。

假设后台一下返回1000条数据,如果我们一次性把它放到页面上,那肯定会造成页面卡顿的,优化思路就是,把列表分割成很多个小数组,然后一段一段的显示到页面。可利用 Api:window.requestAnimationFrame或者setInterval不断填充数据; window.requestAnimationFrame()告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行; // d..
前端长列表加载 什么是长列表? 长列表的出现寓意着本次数据可能会超过1000条甚至为10000条的数据列表, 这时候列表可能会出现问题,出现短暂白屏、或者数据太多导致网页崩溃等情况,尤其在现在的移动端这种情况是非常容易出现的,给予用户的展现机制大部分都是列表 长列表的解决方案公认的有两种,第一种就是无限滚动 前后端共同进行优化, 基本思想就是用户将可视区域的scrollTop滑动成0时进行分页请求 这种方案是一个在正常逻辑正常框架之下的解决方案. 还有一种方案就是虚拟列表, 他的出现主要是由于又一些特殊的场
前端页面卡顿、也许是DOM操作惹的祸? 界面上UI的更改都是通过DOM操作实现的,并不是通过传统的刷新页面实现 的。尽管DOM提供了丰富接口供外部调用,但DOM操作的代价很高,页面前端代码的性能瓶颈也大多集中在DOM操作上,所以前端性能优化的一个主要的关注 点就是DOM操作的优化。DOM操作优化的总原则是尽量减少DOM操作。 先来看看DOM操作为什么会影响性能 在浏览器中,DOM的实现和ECMAScript的实现是分离的。比如 在IE中,ECMAScrit的实现在jscript.dll中,而DOM的实
在做移动端或者其他无限下拉加载时会遇到不断插入dom的场景,随着dom的增多页面会出现卡顿,遇到这种情况开发者会采取一系列的优化措施,比如复用dom等,那么到底为什么会出现卡顿呢?本文将探讨这个疑问。 网页卡顿,那肯定是渲染延迟或者cpu占用过高。 看下面一个实例:
问题:当后端一次性返回数据(array)过多时(例如1000条或者更多),会导致页面卡顿 优化思路:将这1000条数据划分为多个小数组,然后一段一段的加到页面上 解决方案:利用window.requestAnimationFrame()或者setInterval() 示例:以window.requestAnimationFrame()为例 window.requestAnimationFrame()告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要.
2. 对一阶差分进行统计,例如计算其均值和标准差。 3. 如果一阶差分的均值显著大于0,并且标准差也比较大,那么可能存在突增的情况;如果一阶差分的均值显著小于0,并且标准差也比较大,那么可能存在突减的情况。 4. 可以根据具体数据的特点和分析目的,设置阈值来判断是否存在突增或突减情况。 下面是一个简单的matlab代码示例: ```matlab data = [1 2 3 10 11 12 8 9 10]; % 数据 diff_data = diff(data); % 一阶差分 diff_mean = mean(diff_data); % 均值 diff_std = std(diff_data); % 标准差 if diff_mean > 0 && diff_std > threshold % 突增 disp('存在突增情况'); elseif diff_mean < 0 && diff_std > threshold % 突减 disp('存在突减情况'); else % 没有突增或突减 disp('没有突增或突减情况');