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

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

防抖(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 修改元素的布局信息时,浏览器需要重新计算整个页面的布局,所以会触发回流。像添加或删除元素、修改元素的尺寸、改变字体大小等操作都可能导致回流。

区别

  • 防抖和节流:防抖是等用户停止触发事件一段时间后才执行处理函数,强调"停止触发后的延迟执行";节流是在一定时间内只执行一次处理函数,强调"固定时间间隔执行"。
  • 重绘和回流:重绘只改元素外观,不涉及布局信息改变;回流涉及元素布局信息重新计算和排列,开销比重绘大,而且回流通常会引发重绘。
相关推荐
IT、木易18 分钟前
大白话TypeScript第八章TypeScript 项目的部署与监控
前端·javascript·typescript
m0_7482393322 分钟前
SpringMVC新版本踩坑[已解决]
android·前端·后端
bin915342 分钟前
DeepSeek 助力 Vue3 开发:打造丝滑的分页(Pagination)
前端·javascript·vue.js·ecmascript·deepseek
前端切图仔00142 分钟前
UniApp+Vue3实现高性能无限滚动卡片组件:垂直滑动、触摸拖拽与动态导航的完美结合
前端·javascript·vue.js·前端框架·uni-app
小钟H呀1 小时前
Vue3 Hooks:从原理到实战封装指南
前端·javascript·vue.js
三月七(爱看动漫的程序员)1 小时前
Prompt Engineering for Large Language Models
前端·javascript·人工智能·语言模型·自然语言处理·pdf·prompt
我爱学习_zwj2 小时前
1. HTTP 数据请求
前端
pink大呲花2 小时前
ES6笔记总结
前端·笔记·es6
我的div丢了肿么办2 小时前
试试使用 Vitest 进行测试,确实可以减少bug
前端·vue.js·vite
LaughingZhu2 小时前
PH热榜 | 2025-02-28
前端·人工智能·经验分享·搜索引擎·产品运营