防流、节抖、重绘、回流原理,以及实现方法和区别

防流、节抖、重绘、回流原理,以及实现方法和区别,还有就是为什么会出现这种情况?

防抖(Debounce)

原理

防抖就像是你坐电梯,如果你一直不停地按开门按钮,电梯不会每次都开门,而是等你停止按按钮一段时间后,才会执行开门动作。在前端里,当一个事件被频繁触发时,防抖会让事件处理函数在你停止触发一段时间后才执行。比如在搜索框输入联想功能中,用户快速输入文字时,我们不希望每次输入都去请求服务器获取联想词,而是等用户停止输入一小段时间后,再去请求,这样可以减少不必要的请求。

实现方法
javascript 复制代码
function debounce(func, delay) {
    let timer;
    return function () {
        const context = this;
        const args = arguments;
        // 每次触发事件时,清除之前的定时器
        clearTimeout(timer); 
        // 设置新的定时器
        timer = setTimeout(() => {
            func.apply(context, args);
        }, delay);
    };
}

// 使用示例
const input = document.getElementById('searchInput');
input.addEventListener('input', debounce(function () {
    console.log('执行搜索操作');
}, 300));
出现原因

在一些场景中,用户可能会频繁触发某个事件,比如搜索框输入、窗口缩放等。如果每次触发都执行相应的处理函数,会导致性能问题,比如产生大量的网络请求、进行不必要的计算等。防抖可以避免这些问题,提高性能和用户体验。

节流(Throttle)

原理

节流就像你家的水龙头,你把水流调到一定大小,不管你怎么拧水龙头,在一段时间内,水的流量是固定的。在前端里,当一个事件被频繁触发时,节流会让事件处理函数在一定时间内只执行一次。比如在滚动加载数据的场景中,用户滚动页面时,我们不希望滚动一点就加载一次数据,而是每隔一段时间加载一次。

实现方法
javascript 复制代码
function throttle(func, limit) {
    let inThrottle;
    return function () {
        const context = this;
        const args = arguments;
        if (!inThrottle) {
            func.apply(context, args);
            inThrottle = true;
            // 设置定时器,一段时间后重置状态
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

// 使用示例
window.addEventListener('scroll', throttle(function () {
    console.log('滚动加载数据');
}, 200));
出现原因

和防抖类似,在高频触发事件的场景中,为了避免处理函数被过于频繁地执行,导致性能问题,比如滚动加载数据时,如果每次滚动都加载数据,会造成大量的网络请求和数据处理,影响性能。节流可以控制处理函数的执行频率,保证性能稳定。

重绘(Repaint)

原理

重绘就像是你给家里的家具重新刷漆,家具的位置和大小不变,只是外观变了。在网页里,当一个元素的外观发生变化,但没有影响到布局信息(如宽高、位置)时,浏览器会将这个元素的外观重新绘制一遍,这就是重绘。比如改变元素的颜色、透明度等样式。

实现方法

在 CSS 里直接修改元素的外观样式就会触发重绘,例如:

css 复制代码
/* HTML 中有一个 id 为 myElement 的元素 */
#myElement {
    color: red; /* 初始颜色为红色 */
}

/* 使用 JavaScript 修改颜色,触发重绘 */
const element = document.getElementById('myElement');
element.style.color = 'blue'; 
出现原因

当我们通过 CSS 或 JavaScript 修改元素的外观样式时,浏览器需要更新元素在屏幕上的显示,所以会触发重绘。

回流(Reflow,也叫重排)

原理

回流就像是你重新布置家里的家具,改变了家具的位置和大小。在网页里,当一个元素的布局信息(如宽高、位置、边距等)发生变化时,浏览器需要重新计算元素的位置和大小,然后将它们重新排列在页面上,这就是回流。回流的开销比重绘大,因为它不仅要重新绘制元素,还要重新计算布局。

实现方法

修改元素的布局信息会触发回流,例如:

javascript 复制代码
const element = document.getElementById('myElement');
// 修改元素的宽度,触发回流
element.style.width = '200px'; 
出现原因

当我们通过 CSS 或 JavaScript 修改元素的布局信息时,浏览器需要重新计算整个页面的布局,所以会触发回流。像添加或删除元素、修改元素的尺寸、改变字体大小等操作都可能导致回流。

区别

  • 防抖和节流:防抖是在用户停止触发事件一段时间后才执行处理函数,强调的是"停止触发后的延迟执行";节流是在一定时间内只执行一次处理函数,强调的是"固定时间间隔执行"。
  • 重绘和回流:重绘只涉及元素外观的重新绘制,不改变布局信息;回流涉及元素布局信息的重新计算和排列,开销比重绘大。而且回流通常会触发重绘,因为布局改变后,元素的外观也需要重新绘制。

那么,在vue和react中如何进行防流、节抖、重绘、回流原理,以及实现方法和区别

防抖(Debounce)

原理

想象你在电梯里,要是一直狂按开门按钮,电梯不会每次都开门,而是等你停手一小段时间后,才会执行开门动作。在前端里,防抖就是处理频繁触发事件的这种情况,比如搜索框输入,用户快速打字时,我们不想每次按键都去做一些操作(像请求服务器获取联想词),而是等用户停了一小会儿,再去执行对应的操作。

在 Vue 中的实现方法

在 Vue 里,我们可以借助第三方库 lodash 来实现防抖。比如在一个搜索框输入时使用防抖:

vue 复制代码
<template>
  <div>
    <input v-model="keyword" @input="debouncedSearch" placeholder="搜索内容">
  </div>
</template>

<script>
import { debounce } from 'lodash';

export default {
  data() {
    return {
      keyword: ''
    };
  },
  created() {
    // 创建防抖函数,300 毫秒内没有再次触发才执行搜索
    this.debouncedSearch = debounce(this.search, 300);
  },
  methods: {
    search() {
      console.log('执行搜索:', this.keyword);
      // 这里可以放实际的搜索请求代码
    }
  }
};
</script>

这里在 created 生命周期里用 lodashdebounce 函数把 search 方法包装成了防抖函数 debouncedSearch,这样输入框输入事件触发时,只有停顿 300 毫秒才会执行搜索操作。

在 React 中的实现方法

在 React 里同样可以用 lodash 来做防抖。示例如下:

jsx 复制代码
import React, { useState } from'react';
import { debounce } from 'lodash';

function SearchInput() {
  const [keyword, setKeyword] = useState('');

  const search = () => {
    console.log('执行搜索:', keyword);
    // 这里可以放实际的搜索请求代码
  };

  const debouncedSearch = debounce(search, 300);

  const handleInputChange = (e) => {
    setKeyword(e.target.value);
    debouncedSearch();
  };

  return (
    <input
      type="text"
      value={keyword}
      onChange={handleInputChange}
      placeholder="搜索内容"
    />
  );
}

export default SearchInput;

这里创建了一个 debouncedSearch 防抖函数,当输入框内容改变时,调用这个防抖函数,从而实现防抖效果。

出现原因

在很多场景下,用户可能会快速频繁地触发事件,比如输入框输入、窗口缩放等。如果每次触发都执行对应的操作,会造成性能问题,像产生大量不必要的网络请求或者进行重复计算,所以需要防抖来避免这些问题。

节流(Throttle)

原理

节流就像家里的水龙头,你把水流大小固定好,不管你怎么拧水龙头,在一段时间内,水的流量是固定的。在前端里,当一个事件被频繁触发时,节流会让事件处理函数在一定时间内只执行一次。比如滚动加载数据,我们不想滚动一点就加载一次数据,而是每隔一段时间加载一次。

在 Vue 中的实现方法
vue 复制代码
<template>
  <div @scroll="throttledScroll">
    <!-- 这里放滚动内容 -->
  </div>
</template>

<script>
import { throttle } from 'lodash';

export default {
  created() {
    // 创建节流函数,每 200 毫秒最多执行一次滚动处理
    this.throttledScroll = throttle(this.handleScroll, 200);
  },
  methods: {
    handleScroll() {
      console.log('滚动事件触发');
      // 这里可以放滚动加载数据的代码
    }
  }
};
</script>

使用 lodashthrottle 函数把 handleScroll 方法包装成节流函数 throttledScroll,这样滚动事件触发时,每 200 毫秒最多执行一次 handleScroll

在 React 中的实现方法
jsx 复制代码
import React from'react';
import { throttle } from 'lodash';

function ScrollComponent() {
  const handleScroll = () => {
    console.log('滚动事件触发');
    // 这里可以放滚动加载数据的代码
  };

  const throttledScroll = throttle(handleScroll, 200);

  return (
    <div onScroll={throttledScroll}>
      {/* 这里放滚动内容 */}
    </div>
  );
}

export default ScrollComponent;

同样借助 lodashthrottle 函数创建节流函数,绑定到滚动事件上。

出现原因

和防抖类似,在高频触发事件的场景中,为了避免处理函数被过于频繁地执行,导致性能问题,比如滚动加载数据时,如果每次滚动都加载数据,会造成大量的网络请求和数据处理,影响性能,所以需要节流来控制执行频率。

重绘(Repaint)

原理

重绘就好比你给家里的家具重新刷漆,家具的位置和大小不变,只是外观变了。在网页里,当一个元素的外观发生变化,但没有影响到布局信息(像宽高、位置)时,浏览器会把这个元素的外观重新画一遍,这就是重绘。比如改变元素的颜色、透明度等样式。

在 Vue 和 React 中出现的情况及处理

在 Vue 和 React 里,只要修改了元素的外观样式,就可能触发重绘。比如在 Vue 中:

vue 复制代码
<template>
  <div :style="{ color: textColor }">这是一段文字</div>
  <button @click="changeColor">改变颜色</button>
</template>

<script>
export default {
  data() {
    return {
      textColor: 'black'
    };
  },
  methods: {
    changeColor() {
      this.textColor = 'red';
    }
  }
};
</script>

点击按钮改变文字颜色,就会触发重绘。在 React 里也是类似的,通过修改样式来触发重绘:

jsx 复制代码
import React, { useState } from'react';

function RepaintExample() {
  const [textColor, setTextColor] = useState('black');

  const changeColor = () => {
    setTextColor('red');
  };

  return (
    <div>
      <div style={{ color: textColor }}>这是一段文字</div>
      <button onClick={changeColor}>改变颜色</button>
    </div>
  );
}

export default RepaintExample;
出现原因

当我们通过 CSS 或 JavaScript 修改元素的外观样式时,浏览器需要更新元素在屏幕上的显示,所以会触发重绘。

回流(Reflow,也叫重排)

原理

回流就像是你重新布置家里的家具,改变了家具的位置和大小。在网页里,当一个元素的布局信息(像宽高、位置、边距等)发生变化时,浏览器需要重新计算元素的位置和大小,然后把它们重新排列在页面上,这就是回流。回流的开销比重绘大,因为它不仅要重新画元素,还要重新算布局。

在 Vue 和 React 中出现的情况及处理

在 Vue 里,比如动态修改元素的宽度就可能触发回流:

vue 复制代码
<template>
  <div :style="{ width: boxWidth + 'px' }">这是一个盒子</div>
  <button @click="changeWidth">改变宽度</button>
</template>

<script>
export default {
  data() {
    return {
      boxWidth: 100
    };
  },
  methods: {
    changeWidth() {
      this.boxWidth = 200;
    }
  }
};
</script>

在 React 中:

jsx 复制代码
import React, { useState } from'react';

function ReflowExample() {
  const [boxWidth, setBoxWidth] = useState(100);

  const changeWidth = () => {
    setBoxWidth(200);
  };

  return (
    <div>
      <div style={{ width: `${boxWidth}px` }}>这是一个盒子</div>
      <button onClick={changeWidth}>改变宽度</button>
    </div>
  );
}

export default ReflowExample;

点击按钮改变盒子宽度,就会触发回流。

出现原因

当我们通过 CSS 或 JavaScript 修改元素的布局信息时,浏览器需要重新计算整个页面的布局,所以会触发回流。像添加或删除元素、修改元素的尺寸、改变字体大小等操作都可能导致回流。

区别

  • 防抖和节流:防抖是等用户停止触发事件一段时间后才执行处理函数,强调"停止触发后的延迟执行";节流是在一定时间内只执行一次处理函数,强调"固定时间间隔执行"。
  • 重绘和回流:重绘只改元素外观,不涉及布局信息改变;回流涉及元素布局信息重新计算和排列,开销比重绘大,而且回流通常会引发重绘。
相关推荐
Mintopia6 分钟前
3D Quickhull 算法:用可见性与冲突图搭建空间凸壳
前端·javascript·计算机图形学
Mintopia6 分钟前
Three.js 三维数据交互与高并发优化:从点云到地图的底层修炼
前端·javascript·three.js
Code季风10 分钟前
Spring IoC 容器性能提升指南:启动速度与运行效率优化策略
java·spring·性能优化
陌小路12 分钟前
5天 Vibe Coding 出一个在线音乐分享空间应用是什么体验
前端·aigc·vibecoding
成长ing1213820 分钟前
cocos creator 3.x shader 流光
前端·cocos creator
Alo36528 分钟前
antd 组件部分API使用方法
前端
BillKu31 分钟前
Vue3数组去重方法总结
前端·javascript·vue.js
鼠鼠我捏,要死了捏1 小时前
Elasticsearch索引设计与性能优化实战指南
elasticsearch·性能优化·索引设计
江城开朗的豌豆1 小时前
Vue+JSX真香现场:告别模板语法,解锁新姿势!
前端·javascript·vue.js
这里有鱼汤1 小时前
首个支持A股的AI多智能体金融系统,来了
前端·python