JavaScript实现防抖与节流

1. 防抖与节流

1.1 定义

在一定时间之内, 只允许触发事件一次, 防止多次触发.

1.2 区别
  • 防抖的意义在执行的是用户最后一次触发的事件, 而节流执行的是用户第一次触发的事件.
1.3 场景重现
  • 防抖: 输入搜索框随时监听用户键盘输入, 及时返回关于搜索的关键字供用户选择, 如何解决用户敲一下键盘我们就调用一次服务器, 频繁调用服务器, 增大服务器的开销的问题?
  • 节流: 前端调用服务端接口, 在接口没有返回的同时, 我们如何防止用户再次点击事件按钮多次执行数据?
1.4 解决思路
  • 防抖: 我们可以 延迟执行 触发函数, 一旦还没有执行函数用户再次触发事件, 那么我们抛弃上一步的事件执行最新一次的事件. 关键字 延迟执行. 核心代码如下:
 // 监听键盘事件模拟搜索场景.
        let shakeTimeOut = null;
        searchBox.addEventListener("keyup", function () {
            let value = searchBox.value.trim();
            if (!value) {
                return false;
            }
            // 只要重新输入清空以前的定时任务
            if (shakeTimeOut) {
                clearTimeout(shakeTimeOut);
            }
            // 重新定义最新的定时任务
            shakeTimeOut = setTimeout(function () {
                // 真正执行函数部分
                console.debug(value);
            }, 1000);
        });
  • 节流 我们可以 通过控制一段时间内关键字状态 来执行函数. 核心代码如下:
			// 利用 saveStreamFlag 关键字控制代码执行
        let saveStreamFlag = true;
        searchBtn.addEventListener("click", function () {
            if (!saveStreamFlag) {
                console.debug("搜索值太频繁");
                return false;
            }
            saveStreamFlag = false;
            saveStream();
            // 执行 saveStream() 方法的时间不会影响改变 saveStreamFlag标识改变的时间
            setTimeout(function () {
                saveStreamFlag = true;
              // 我们可以预估方法执行的时间来改变标识的时间
            }, 1000);
        });
1.5 逻辑代码

代码中涉及到了利用H5创建本地数据库, 一旦触发搜索, 我们将用户搜索的记录存储在数据库中, 利用input[list] 和datalist 标签实现输入搜索框的实现(代码中涉及背景图片和字体资源请忽略).

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>Js实现防抖和节流</title>
</head>
<style type="text/css">
    * {
        margin: 0;
        padding: 0;
    }

    /*定义外部网络字体*/
    @font-face {
        font-family: WebFont;
        src: url("font/ErZiYuanMoFaShaoNvJian-2.ttf");
    }

    body {
        font-family: WebFont;
        font-size: 20px;
        background: black;
    }
    #box {
        margin: auto;
        width: 1280px;
        height: 800px;
        background-image: url("image/backend.jpg");
        background-size: cover;
        border: none;
    }

    #content {
        position: fixed;
        top: 20%;
        left: 50%;
        transform: translateX(-50%);
        display: table;
        text-align: center;
        color: #e91e63;
    }

    #content section {
        display: inline-block;
        width: 500px;
        height: 300px;
    }

    #preventShakeBox input{
        height: 30px;
        line-height: 30px;
        outline: none;
        border-radius: 5px;
        border: none;
        padding-left: 5px;
    }
    #preventShakeBox input::placeholder {
        color: #999999;
    }

    #saveStreamBox input{
        height: 30px;
        line-height: 30px;
        outline: none;
        border-radius: 5px;
        border: none;
        padding: 0 20px;
        cursor: pointer;
    }

    #saveStreamBox input:hover {
        background-color: #e91e63;
        color: #ffffff;
    }

</style>
<body>
    <div id="box">
        <section id="content">
            <h1>Js实现防抖与节流</h1>
            <section id="preventShakeBox">
                <h2>防抖</h2>
                <!--利用 input 和 datalist 标签绑定实现可输入和下拉的功能-->
                <input type="text" placeholder="请输入要搜索的值" aria-label="防抖" list="data" id="searchBox"/>
                <datalist id="data">
                </datalist>
            </section>
            <section id="saveStreamBox">
                <h2>节流</h2>
                <input type="button" value="搜索" id="searchBtn">
            </section>
        </section>
    </div>
</body>
<script type="text/javascript">
    /*将搜索的值存入本地数据库*/
    let db = openDatabase("db_search", "1.0", "test prevent shake and save stream", 1024 * 1024 * 2);
    let searchBtn = document.getElementById("searchBtn");
    let searchBox = document.getElementById("searchBox");
    let data = document.getElementById("data");

    // 创建数据库
    db.transaction(function (transaction) {
        transaction.executeSql(" drop table if exists search_history");
        transaction.executeSql(" create table search_history ( key varchar(255) unique not null)" ,
            [], function () {
            console.debug("数据库创建成功");
        }, function (transaction, error) {
            console.debug("数据库创建失败, 失败原因是: " + error.message);
        });
    });

    window.onload = function () {

        // 将搜索的值插入数据库并刷新datalist的值
        let saveStreamFlag = true;
        searchBtn.addEventListener("click", function () {
            if (!saveStreamFlag) {
                console.debug("搜索值太频繁");
                return false;
            }
            saveStreamFlag = false;
            saveStream();
            // 执行 saveStream() 方法的时间不会影响改变 saveStreamFlag标识改变的时间
            // 我们可以预估方法执行的时间来改变标识的时间
            setTimeout(function () {
                saveStreamFlag = true;
            }, 1000);
        });



        // 监听键盘事件模拟搜索场景.
        let shakeTimeOut = null;
        searchBox.addEventListener("keyup", function () {
            let value = searchBox.value.trim();
            if (!value) {
                return false;
            }
            // 只要重新输入清空以前的定时任务
            if (shakeTimeOut) {
                clearTimeout(shakeTimeOut);
            }
            // 重新定义最新的定时任务
            shakeTimeOut = setTimeout(function () {
                console.debug(value);
            }, 1000);
        });
    };

    // 刷新datalist的值
    function flushDataList(transaction) {
        transaction.executeSql("select * from search_history", [], function (transaction,resultSet) {
            let rows = resultSet.rows;
            let options = "";
            for (let i = 0; i < rows.length; i++) {
                let name = rows[i].key;
                console.debug(name);
                options += `<option value="${name}">${name}</option>`;
            }
            data.innerHTML = options;
        }, function (transaction, error) {
            console.debug("查询历史记录失败, 失败原因为: " + error.message);
        });
    }

    function saveStream() {
        const value = searchBox.value.trim();
        if (!value) {
            console.debug("搜索参数不能为空");
            return false;
        }
        console.debug("参加搜索的值为: " + value);
        db.transaction(function (transaction) {
            transaction.executeSql("select * from search_history where key = ? ", [new Object(value)], function (transaction, resultSet) {
                let rows = resultSet.rows;
                if (rows.length <= 0) {
                    transaction.executeSql("insert into search_history(key) values( ? )", [new Object(value)], function () {
                        console.debug("插入成功");
                    }, function (transaction, error) {
                        console.debug("插入失败, 失败原因: " + error.message);
                    });
                    flushDataList(transaction);
                }
            }, function (transaction, error) {
                console.debug("查询历史记录失败, 失败原因为: " + error.message);
            });
        });
    }

</script>
</html>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值