面试题答案
一键面试函数封装
- 通用防抖函数封装:
const debounce = (func, delay) => { let timer; return function(...args) { const context = this; clearTimeout(timer); timer = setTimeout(() => { func.apply(context, args); }, delay); }; };
- 通用节流函数封装:
const throttle = (func, limit) => { let inThrottle; return function(...args) { const context = this; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; };
依赖管理
- 使用ES6模块:将防抖和节流函数封装成独立的模块,在需要使用的组件中按需导入。
// debounce.js export const debounce = (func, delay) => { //... }; // component.js import { debounce } from './debounce.js';
- 避免重复引入:确保在整个项目中,防抖和节流函数只被引入一次,避免重复定义造成的性能浪费。
内存优化
- 清除定时器:在组件卸载时,手动清除防抖和节流函数内部的定时器,防止内存泄漏。
- 使用Hooks:
import React, { useEffect, useRef } from'react'; import { debounce } from './debounce.js'; const MyComponent = () => { const debouncedFunc = useRef(debounce(() => { // 执行的逻辑 }, 500)).current; useEffect(() => { return () => { // 清除定时器 clearTimeout(debouncedFunc.timer); }; }, []); return <div>Component</div>; };
- 使用类组件:
import React, { Component } from'react'; import { debounce } from './debounce.js'; class MyComponent extends Component { constructor(props) { super(props); this.debouncedFunc = debounce(() => { // 执行的逻辑 }, 500); } componentWillUnmount() { clearTimeout(this.debouncedFunc.timer); } render() { return <div>Component</div>; } }
利用React特性管理和复用防抖节流逻辑
- 上下文(Context):可以通过创建一个防抖节流上下文,将通用的防抖节流函数注入到需要的组件树中。
在子组件中使用:import React from'react'; const DebounceThrottleContext = React.createContext(); const DebounceThrottleProvider = ({ children }) => { const debounce = (func, delay) => { //... }; const throttle = (func, limit) => { //... }; return ( <DebounceThrottleContext.Provider value={{ debounce, throttle }}> {children} </DebounceThrottleContext.Provider> ); }; export { DebounceThrottleContext, DebounceThrottleProvider };
import React from'react'; import { DebounceThrottleContext } from './DebounceThrottleContext.js'; const MyComponent = () => { const { debounce } = React.useContext(DebounceThrottleContext); const debouncedFunc = debounce(() => { // 执行的逻辑 }, 500); return <div>Component</div>; };
- 高阶组件(HOC):创建高阶组件来复用防抖节流逻辑。
import React from'react'; import { debounce } from './debounce.js'; const withDebounce = (func, delay) => { return WrappedComponent => { return class extends React.Component { constructor(props) { super(props); this.debouncedFunc = debounce(func.bind(this), delay); } componentWillUnmount() { clearTimeout(this.debouncedFunc.timer); } render() { return <WrappedComponent {...this.props} debouncedFunc={this.debouncedFunc} />; } }; }; }; const MyFunction = () => { // 执行的逻辑 }; const MyComponent = withDebounce(MyFunction, 500)(props => { return ( <div> <button onClick={props.debouncedFunc}>Click</button> </div> ); });
- Hooks:自定义Hooks来复用防抖节流逻辑。
import React, { useEffect, useRef } from'react'; import { debounce } from './debounce.js'; const useDebounce = (func, delay) => { const debouncedFunc = useRef(debounce(func, delay)).current; useEffect(() => { return () => { clearTimeout(debouncedFunc.timer); }; }, []); return debouncedFunc; }; const MyComponent = () => { const myFunction = () => { // 执行的逻辑 }; const debouncedFunc = useDebounce(myFunction, 500); return <div><button onClick={debouncedFunc}>Click</button></div>; };
与Redux结合
- 在Action中使用:在Redux的action creators中使用防抖或节流,防止频繁触发相同的action。
import { debounce } from './debounce.js'; import { FETCH_DATA } from './actionTypes.js'; const fetchData = () => ({ type: FETCH_DATA }); const debouncedFetchData = debounce(fetchData, 500); export { debouncedFetchData };
- 在中间件中处理:可以利用Redux中间件(如redux-thunk)来处理防抖节流的逻辑,使action creators保持纯净。
import { debounce } from 'lodash'; import { FETCH_DATA } from './actionTypes.js'; const debounceMiddleware = store => next => action => { const { type } = action; if (type === FETCH_DATA) { const debouncedAction = debounce(() => { next(action); }, 500); debouncedAction(); } else { next(action); } }; export default debounceMiddleware;