防抖和节流,主要是用来防止过于频繁的执行某个操作,如浏览器窗口变化执行某个操作,监听某个input输入框keyup变化,瀑布流布局时Y轴滚动,图片加载。
/* 不做处理input触发keyup事件 */
/* 输入快的话会出现输出结果多次重复 */
window.onload = function () {
let obj = document.getElementById('input')
obj.addEventListener('keyup',()=>{
let val = obj.value;
inputchange(val)
},false)
}
function inputchange(val) {
console.log(val)
}
防抖处理
/* 使用防抖去处理input触发keyup事件 */
window.onload = function () {
let obj = document.getElementById('input')
let callback = inputchange()
obj.addEventListener('keyup',()=>{
let val = obj.value;
callback(val)
},false)
}
// 高级函数的应用
// 闭包time为局部变量 但不会在inputchange 函数调用完后释放
// 函数返回函数
function inputchange() {
var time
return function(val){
if(time)
{
clearTimeout(time)
}
time = setTimeout(() => {
console.log(val)
}, 200);
}
}
节流
定义:执行某个操作后一段时间内不再进行该操作
/* 使用节流去处理input触发keyup事件 */
/* 输入快的话会也不会输出多次重复结果 */
window.onload = function () {
let obj = document.getElementById('input')
let callback = inputchange()
obj.addEventListener('keyup',()=>{
let val = obj.value;
callback(val)
},false)
}
// 使用闭包保存hasdone
function inputchange() {
var hasdone = false
return function(val){
// 如果已经执行 hasdone = true 则直接返回
if(hasdone)
{
return;
}
// 设置已经执行
console.log(val)
hasdone =true
/* 一段时间后设置hasdone 为能够再次执行 */
time = setTimeout(() => {
hasdone = false
}, 2000);
}
}
上面的节流,第一次输入马上执行,是最后输入不执行。
还有就是第一次输入不马上执行,时间内最后执行
/* 使用节流去处理input触发keyup事件 */
/* 输入快的话会也不会输出多次重复结果 */
window.onload = function () {
let obj = document.getElementById('input')
let callback = inputchange()
obj.addEventListener('keyup',()=>{
let val = obj.value;
callback(val)
},false)
}
// 使用闭包保存hasdone
/* 时间内不马上执行,时间段内只执行一次 */
function inputchange() {
var hasdone = false
var time = null
return function(val){
// 如果已经执行 hasdone = true 则直接返回
if(hasdone)
{
return;
}
// 设置已经执行
hasdone =true
/* 一段时间后设置hasdone 为能够再次执行 */
time = setTimeout(() => {
console.log(val)
hasdone = false
}, 500);
}
}
节流与防抖的区别
节流与防抖的前提都是某个行为持续地触发,不同之处只要判断是要优化到减少它的执行次数还是只执行一次就行。
-
节流例子,像dom的拖拽,如果用消抖的话,就会出现卡顿的感觉,因为只在停止的时候执行了一次,这个时候就应该用节流,在一定时间内多次执行,会流畅很多。
-
防抖例子,像仿百度搜索,就应该用防抖,当我连续不断输入时,不会发送请求;当我一段时间内不输入了,才会发送一次请求;如果小于这段时间继续输入的话,时间会重新计算,也不会发送请求。
更为简单的一种写法:
转载自:浅谈js防抖和节流
这个相对于容易理解一些。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
height: 300px;
}
div:nth-of-type(odd){
background-color: red;
}
div:nth-of-type(even){
background-color: yellow;
}
</style>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<script type="text/javascript">
// 防抖
// 短时间内连续触发的事件(上面的滚动事件),防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次。
function debounce(fn,delay){
let timer = null
return function(){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fn, delay);
}
}
// 函数节流
// 如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效
// 如果一直拖着滚动条进行滚动,那么会以1s的时间间隔,持续输出当前位置和顶部的距离
function throttle(fn,delay){
let valid = true;
return function(){
if(!valid){
return false;
}
valid = false;
setTimeout(() => {
fn()
valid = true;
},delay);
}
}
function showTop(){
var scrollTop = document.scrollTop || document.documentElement.scrollTop;
console.log('滚动条:'+scrollTop);
}
// window.onscroll = debounce(showTop,1000);
window.onscroll = throttle(showTop,1000);
</script>
</body>
</html>
详细可查看这篇转载的链接。
js 实现浏览器滚动条滚动到最下面时,加载更多数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./js/fangdouhejl.js"></script>
<style>
.box{
height:890px;
}
li{
height: 60px;
}
.loading{
width: 80px;
height: 40px;
margin: 0 auto;
margin-top:100px;
display: none;
}
.loading span{
display: inline-block;
width: 8px;
height: 100%;
border-radius: 4px;
background: lightgreen;
-webkit-animation: load 1s ease infinite;
}
@-webkit-keyframes load{
0%,100%{
height: 40px;
background: lightgreen;
}
50%{
height: 70px;
margin: -15px 0;
background: lightblue;
}
}
.loading span:nth-child(2){
-webkit-animation-delay:0.2s;
}
.loading span:nth-child(3){
-webkit-animation-delay:0.4s;
}
.loading span:nth-child(4){
-webkit-animation-delay:0.6s;
}
.loading span:nth-child(5){
-webkit-animation-delay:0.8s;
}
</style>
</head>
<body>
<ul id="box">
<li>baojia1</li>
<li>baojia2</li>
<li>baojia3</li>
<li>baojia4</li>
<li>baojia5</li>
<li>baojia6</li>
<li>baojia7</li>
<li>baojia8</li>
<li>baojia9</li>
<li>baojia10</li>
<li>baojia11</li>
<li>baojia12</li>
<li>baojia13</li>
<li>baojia14</li>
<li>baojia15</li>
<li>baojia16</li>
<li>baojia17</li>
<li>baojia18</li>
<li>baojia19</li>
<li>baojia20</li>
</ul>
<div class="loading" id="loading">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</body>
</html>
fangdouhejl.js:
/* 浏览器滚动事件onsroll */
/* 实现浏览器滚动到最下面实现加载 */
var loadmore = loadmoreresource ();
/* 模仿滚到最下面继续加载数据 */
window.onscroll = function (e) {
/* 判断是否滚到最下面 */
/* 如果已经滚到最下面则执行某个操作 */
var e =e || window.event;
// 为了兼容谷歌和火狐 document.body.scrollTop是谷歌上的
/* 滚动条的垂直位置 */
var scrolltop = document.documentElement.scrollTop||document.body.scrollTop;
/* 整个页面的正文高度 */
var scrollHeight = document.documentElement.scrollHeight||document.body.scrollHeight;
/* 可见区域高度 */
var clientHeight = document.documentElement.clientHeight||document.body.clientHeight;
/* 当scrolltop加clientHeight 等于scrollHeight */
if(scrollHeight === (scrolltop+clientHeight))
{
loadmore();
}
}
/* 往下拉时加载的数据 */
/* 使用函数节流优化加载,否则会出现一次性加载很多次 */
function loadmoreresource () {
let i = 21;
/* 定义是否已经加载 */
let isloading = false;
return function () {
/* 假如已经在加载中了则直接返回 */
if(isloading) {
return;
}
/* 出现加载动画 */
loadingimg()
let obj = document.getElementById('box');
/* 代码片段 用于插入多个标签 */
let docfragment = document.createDocumentFragment();
for(let j=0;j<5;j++){
let li = document.createElement('li')
li.append('baojia'+i)
docfragment.appendChild(li)
i++;
}
/* 设置当前加载的状态为true */
isloading = true;
/* 使用setTimeout 模拟从api加载数据 */
setTimeout(() => {
obj.appendChild(docfragment)
loadingimg()
/* 将加载状态设置为false */
isloading = false
}, 3000);
}
}
/* 加载动画 */
function loadingimg() {
let loading = document.getElementById('loading');
if(loading.style.display==='block') {
loading.style.display = 'none';
} else {
loading.style.display = 'block';
}
}
转自:js防抖和节流优化浏览器滚动条滚动到最下面时加载更多数据
作者:waitklove