搜索框优化策略 函数去抖(debounce)
业务场景
我们在项目中往往会使用到很多搜索框,这些搜索框一般会用AutoComplete组件或者或者Select组件加showSearch属性来实现,然后把模糊搜索的逻辑写在onSearch里.
但是如果只这样写的话,就会产生如下效果,只要我们输入的值发生变化,就会发送请求.由于中文的特殊性,这里会产生很多的无用请求,如果响应较慢,甚至会引起页面卡顿.
比如我们使用现在大多数人都会使用的搜狗输入法。
在上边这一个字未输入完之前,就已经发出了4条请求,
请求参数依次是 m me men meng
解决方案 debounce去抖
当调用函数n秒后,才会执行该动作,若在这n秒内又调用该函数则将取消前一次并重新计算执行时间.
AntD给出的防抖Select逻辑 https://ant.design/components/select-cn/
import { Select, Spin } from 'antd';
import debounce from 'lodash/debounce';
const { Option } = Select;
class UserRemoteSelect extends React.Component {
constructor(props) {
super(props);
this.lastFetchId = 0;
this.fetchUser = debounce(this.fetchUser, 800);
}
state = {
data: [],
value: [],
fetching: false,
};
fetchUser = value => {
console.log('fetching user', value);
this.lastFetchId += 1;
const fetchId = this.lastFetchId;
this.setState({ data: [], fetching: true });
fetch('https://randomuser.me/api/?results=5')
.then(response => response.json())
.then(body => {
if (fetchId !== this.lastFetchId) {
// for fetch callback order
return;
}
const data = body.results.map(user => ({
text: `${user.name.first} ${user.name.last}`,
value: user.login.username,
}));
this.setState({ data, fetching: false });
});
};
handleChange = value => {
this.setState({
value,
data: [],
fetching: false,
});
};
render() {
const { fetching, data, value } = this.state;
return (
<Select
mode="multiple"
labelInValue
value={value}
placeholder="Select users"
notFoundContent={fetching ? <Spin size="small" /> : null}
filterOption={false}
onSearch={this.fetchUser}
onChange={this.handleChange}
style={{ width: '100%' }}
>
{data.map(d => (
<Option key={d.value}>{d.text}</Option>
))}
</Select>
);
}
}
ReactDOM.render(<UserRemoteSelect />, mountNode);
优化结果
主要逻辑代码
this.fetchUser = debounce(this.fetchUser, 800);
在 输入框进行输入后,只有在内容0.8秒未发生变化后,才会发送请求.这样可以有效减少无用请求的次数,也避免了频繁请求造成的页面卡顿.