本文已参与[新人创作礼]活动,一起开启掘金创作之路。
之前看了《金字塔原理》这本书,讲了写作时需要遵循的流程:
背景–冲突–问题–解决方案
背景:
为什么需要防抖函数,在实际开发过程中,当输入搜索框去实时获取后端请求时,输入一个字符都会去请求一次后端,
冲突:
这是非常消耗性能的,我们需要对其进行优化,当监听到input框中数据发生变化时,500ms之后才去请求一次后端接口
问题:
那么我们应该如何去解决这个问题
解决方案:
定义一个防抖函数,传入需要调取接口的方法和延迟定时器的时间,里面先定义一个定时器,返回一个内部函数,这里面判断 如果此时上一次定时器存在,则把上一次的定时器给清除,再定义一个新的定时器,在定时器中去 调用传进来的函数,并且利用apply()改变this指向,以及把args参数给传回去,我使用React 类式组件和函数式组件都尝试了一下,在防抖函数中,类式组件调用this指向组件实例,函数式组件没有this,this值为undefined
自定义防抖函数:
export function debounce(fn, waitTime = 500) {
let time = null; //首次进来时定义一个定时器
return function (args) {
//普通函数内部,arguments为特殊的类数组对象。包含了函数被调用时的参数列表。
if (time) {
clearTimeout(time); //如果上一次定时器存在,则把上一次的定时器给清除
}
//设置定时器
time = setTimeout(() => {
console.log("this", this); //类式组件调用this指向组件实例,函数式组件没有this this值为undefined
fn.apply(this, [args]); //fn直接调用指向window,apply改变this指向,指向调用的环境
}, waitTime);
};
}
复制代码
1. 函数式组件:
export default function DebounceFc() {
const onSearch = (value: string) => console.log(value);
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
console.log(e.target.value);
// 在此调用后端接口
};
const onChangeDebounce = debounce(onChange, 500); //debounce 传入执行的方法 和延迟加载的时
return (
<div style={{ marginTop: 50, marginLeft: 100 }}>
<Search
placeholder="input search text"
onSearch={onSearch}
style={{ width: 200 }}
onChange={(e) => onChangeDebounce(e)} //当输入框内数据发生变化时,调用onChangeDebounce 函数
/>
</div>
);
}
复制代码
打印结果:
2. 类式组件
export class Debounce1 extends Component {
constructor(props: any) {
super(props);
this.onSearch = this.onSearch.bind(this);
this.onChange = this.onChange.bind(this);
this.onChangeDebounce = this.onChangeDebounce.bind(this);
//onChange即是中间变量,由于onChangeDebounce是作为onChange的回调,所以不是通过实例调用的,是直接调用,所以处理函数中,会把函数当成window环境下的独立的函数调用,然后他的this指向全局window
//this指向会丢失。解决这个问题就是给调用函数时bind(this)
//从而使得无论事件处理函数如何传递,this指向都是当前实例化对象,如果不用bind(this),可以用箭头函数 ,箭头函数的this指向他的上下文
}
onSearch(value: string) {
console.log(value);
}
onChange(e: React.ChangeEvent<HTMLInputElement>) {
console.log(e.target.value);
// 在此调用后端接口
}
onChangeDebounce = debounce(this.onChange, 500); //debounce 传入执行的方法 和延迟加载的时间
render() {
return (
<div style={{ marginTop: 50, marginLeft: 100 }}>
<Search
placeholder="input search text"
onSearch={this.onSearch}
style={{ width: 200 }}
onChange={this.onChangeDebounce} //当输入框内数据发生变化时,调用onChangeDebounce 函数
/>
</div>
);
}
}
复制代码
打印结果:
另外:
因为之前我没有开发时没用class声明组件,直接用的hooks,然后去搜索了一下类式组件中调用函数需要用bind()去绑定一下当前组件的this,由于onChangeDebounce是作为onChange的回调,所以不是通过实例调用的,是直接调用,所以处理函数中,然后他的this指向全局window,this指向会丢失。
解决这个问题就是给调用函数时bind(this),从而使得无论事件处理函数如何传递,this指向都是当前实例化对象,如果不用bind(this),可以用箭头函数 ,箭头函数的this指向他的上下文
若文中有误,忘大佬指出
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END