前端性能优化防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清零 clearTimeout。防抖可以比作等电梯,只要有一个人进来,就需要再等一会儿。业务场景有避免登录按钮多次点击的重复提交。
多次触发事件时清除上一次触发的setTimeout,保证setTimeOut中的function在最近一次触发事件后的delayed时间才执行。
本文参考了这个https://github.com/zhaodongming/debounce-throttling
vue代码实现:
html部分(用了elementUI框架)
<el-form
:model="param"
:rules="rules"
ref="param"
label-width="80px"
class="ms-content"
>
<el-form-item
prop="username"
label="账号:"
style="margin-bottom:42px"
>
<el-input
prefix-icon="iconfont el-icon-user"
v-model="param.username"
placeholder="请输入用户名"
></el-input>
</el-form-item>
<el-form-item prop="password" label="密码:">
<el-input
prefix-icon="iconfont el-icon-lock"
type="password"
placeholder="请输入密码"
v-model="param.password"
>
</el-input>
</el-form-item>
<el-button
id="submitbtn"
style="width:100%;height:40px;margin-top:20px"
type="primary"
>登录</el-button
>
</el-form>
js
下面的clickFun 设置了delayed为1000,当鼠标在点击登录按钮时,连续快速点击n次,每次间隔不超过1秒钟,点击第一次后不到一秒再点击第二次,则第一次的setTimeOut事件被clearTimeout清除,以此类推,当点击第n次后1秒内不再点击,则不再执行clearTimeout,setTimeOut中的function方法执行。
<script>
export default {
data() {
return {
param: {
username: '',
password: '',
type: ''
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' }
],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
}
};
},
mounted() {
this.submitFun();
},
methods: {
submitFun() {
let domSubmit = document.getElementById('submitbtn');
let clickFun = this.debounce(() => {
console.log('防抖成功');
this.submitForm('param');
}, 1000);
domSubmit.addEventListener('click', clickFun); // 监听click事件
window.onkeydown = function(event) { // 监听回车登录事件
var e = event || window.event;
if (e && e.keyCode == 13) {
//回车键的键值为13
//调用登录按钮的登录事件
clickFun();
}
};
},
debounce(fun, delayed) {
let timeout = null;
// 使用闭包,让每次调用时点击定时器状态不丢失
return function() {
let context = this;
let args = arguments;
clearTimeout(timeout); // 多次触发事件时清除上一次触发的setTimeout,保证setTimeOut中的function在最近一次触发事件后的delayed时间才执行。
timeout = setTimeout(function() {
fun.apply(context, args);
}, delayed);
};
},
// 这个submitForm中的方法是项目需要,里面不用照抄
submitForm(formName) {
const params = this.param;
this.$refs[formName].validate(valid => {
if (valid) {
this.axios
.post('/xxx/login', {
grantType: 'password',
account: this.param.username,
password: this.param.password,
clientType: 0
})
.then(res => {
if (res.data.Type == 200) {
sessionStorage.setItem('user_token', res.data.Data.AccessToken);
this.axios
.get('/xxx/xxx', {
headers: {
Authorization:
'Bearer ' + sessionStorage.getItem('user_token')
}
})
.then(info => {
if (info.data == 'MainMenu') {
this.$message.success('登录成功');
localStorage.setItem('ms_username', this.param.username);
this.$router.push('/route/xxx');
} else {
this.$message.warning('token错误,请重新登录!');
}
})
.catch(err => {
console.log(err);
});
} else {
this.$message.error(res.data.Content);
}
})
.catch(err => {
console.log(err);
});
} else {
console.log('error submit!!');
return false;
}
});
}
}
}
</script>
html示例移步https://github.com/zhaodongming/debounce-throttling