【问题标题】:How to prevent JavaScript lag from multiple button clicks?如何防止 JavaScript 因多次单击按钮而滞后?
【发布时间】:2021-02-18 14:16:43
【问题描述】:

我正在使用 Vanilla Javascript 开发 Odin Project Etch-A-Sketch 项目:more details

实时预览:https://purplepineapple123.github.io/etch-a-sketch/

首先,我在 javascript 中动态创建了一个 div 网格,并成功创建了按钮(黑色、迷幻和用户颜色选择)来更改 mouseEnter 上每个子 div 网格元素的颜色。

我遇到的问题是优化之一。每次用户单击按钮时,都会触发该事件,并且不会在随后的按钮单击中忘记该事件。例如,如果您点击“迷幻按钮”5 次,然后将鼠标悬停在网格上,console.log 会为您悬停的每个网格显示 5 次该颜色。

注意this 屏幕截图中仅突出显示了 1 个网格,但颜色 console.log 为每个按钮按下分层 div(我在此示例中向 psychedelic-button 发送了垃圾邮件。

这种分层问题在“选择颜色”按钮上确实加剧了。如果用户使用颜色选择器选择多种不同的颜色,console.log 会显示每个 mouseEnter 事件的指数重复输出。这会导致大量延迟。

我尝试过的事情:

  • 添加和删除类而不是更改背景颜色。这很好用,只是我想不出一种将迷幻(随机 JS 选择的颜色)添加到 css 类的方法。
  • 删除 createGrid() 主函数之外的颜色更改函数。这并没有影响任何事情,因为我认为问题是由多次单击按钮引起的。
  • 将颜色更改函数移到 createGrid() 函数之外。然后抓住 divCol 类。将该节点列表转换为数组。为每个元素添加一个 mouseEnter eventListener,然后更改颜色。每次单击按钮时都会出现重复问题。

如何防止此 div 堆叠并因累积的按钮点击而滞后?

我的代码:

HTML

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]>      <html class="no-js"> <!--<![endif]-->
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
     
        
    <main id="main-content">         
            <div id="description-container">
                <h1 class="animate" id="title">text h1</h1>
                <p class="animate" id="desc 1">Text p</p>
            </div>
            <div id="button-container">
                <button id="black-button">Black</button>
                <button id="psych-button">Pschedelic</button>
                <div>
                    <input type="color" name="chooseColor" id="chooseColor"
                    value="#9e0a00">
                    <label for="chooseColor">Choose A Color</label>
                </div>
                <!-- <button id="sixteenGrid" >Normal</button>
                <button id="fourtyGrid">Large</button> -->
                <button id="erase-button">Erase</button>
                <button id="reset-button">Reset</button>
            </div>
            <div id="grid-container"></div>
            <!-- <div class="sliderContainer">
                <button id="reset-button"></button>
                <input type="range" min="1" max="50" value="25" class="slider" id="myRange">
            </div> -->
     </main>
        <script src="main.js" async defer></script>
    </body>
</html>

JavaScript

//Generate grid to size of user input

function createGrid(widthHeight){
    document.getElementById(`grid-container`).innerHTML = "";

    for (let i = 0; i < widthHeight; i++) {
        let divRow = document.createElement(`div`);
        divRow.classList.add(`divRow`);
        document.getElementById(`grid-container`).appendChild(divRow);
        for (let y = 0; y < widthHeight; y++){
            let divCol = document.createElement(`div`);
            divCol.classList.add(`divCol`);
            divRow.appendChild(divCol);


            //default hover
            divCol.addEventListener("mouseenter", function(){
                this.classList.add(`black-button`);
                this.classList.remove(`psych-button`);
            });

            //black button
            document.getElementById(`black-button`).addEventListener(`click`, function() {
                divCol.addEventListener("mouseenter", function(){
                    this.style.backgroundColor = `black`;
                });
            });

            //psychedlic button selection
            document.getElementById(`psych-button`).addEventListener(`click`, function() {
                divCol.addEventListener("mouseenter", function(){
                    this.style.backgroundColor = `#${randomColor()}`;
                });
            });

            //Choose color button
            document.getElementById(`chooseColor`).addEventListener(`input`, function() {
                divCol.addEventListener("mouseenter", function(){
                    this.style.backgroundColor = `${chooseColor()}`;
                });
            }, false);

            //eraser button
            document.getElementById(`erase-button`).addEventListener(`click`, function() {
                divCol.addEventListener("mouseenter", function(){
                    this.style.backgroundColor = `rgb(156, 149, 136)`;

                });
            }); 
        }  
    }
}

createGrid(5);

//return the color choosen by the user
function chooseColor(){
  let color = document.getElementById(`chooseColor`).value;
    console.log(color);
    return color;
}

//returns random colors for psychedleic button
function randomColor() {
    let randomColor = Math.floor(Math.random()*16777215).toString(16);
    console.log(randomColor);
    return randomColor;
}

CSS

/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
    display: block;
}
body {
    line-height: 1;
    background-color: aqua;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}

button {
    padding: 15px;
}

/* begin CSS styling */

#main-content {

    display: flex;
    width: 100%;
    height: 100vh;
    flex-direction: column;
}

#description-container {
    background-color: orange;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
    margin-top: 3%;
}

#button-container {
    background-color: green;

    margin-left: auto;
    margin-right: auto;
    display: inline-flex;
    margin-top: 1%;
}

#grid-container {
    background-color: rgb(156, 149, 136);
    display: flex;
    flex-direction: column;
    margin-left: auto;
    margin-right: auto;
    width: 600px;
    height: 600px;
    text-align: center;
    margin-top: 1%;
}

.divRow {
    display: flex;
    width:100%;
    height:100%;
    margin-top: 1px;
}

.divCol {
    flex: auto;
    border-right: 1px solid #ccc;
    border-bottom:1px solid #ccc;
    margin-right: 1px;
}  

  .reset-color{
      background-color: rgb(156, 149, 136);
  }

  .black-button {
      background-color: black;
  }

  .psych-button {
      background-color: red;
  }

【问题讨论】:

    标签: javascript html css


    【解决方案1】:

    您的问题是,您当前每次单击其中一个按钮时都在创建新的事件侦听器。这些永远不会被破坏,所以当你向你的 psych-button 发送垃圾邮件时,你会创建一堆事件监听器,当你进入一个正方形时,它们都会持续存在并全部触发。

    更好的方法是创建一次事件侦听器,并为颜色保留一个全局变量,并且仅在您单击其中一个按钮时更新它。

    let color = ""; // new variable to hold color value
    
    function createGrid(widthHeight) {
        document.getElementById(`grid-container`).innerHTML = "";
    
        for (let i = 0; i < widthHeight; i++) {
            let divRow = document.createElement(`div`);
            divRow.classList.add(`divRow`);
            document.getElementById(`grid-container`).appendChild(divRow);
            for (let y = 0; y < widthHeight; y++) {
                let divCol = document.createElement(`div`);
                divCol.classList.add(`divCol`);
                divRow.appendChild(divCol);
                divCol.addEventListener("mouseenter", function () {
                    this.style.backgroundColor = color;
                });
            }
        }
    }
    
    createGrid(5);
    
    //black button
    document.getElementById(`black-button`).addEventListener(`click`, function () {
        color = "black";
    });
    

    要让您的 psych-button 使用这个新设置,您可以存储一个全局布尔值,该值定义是否应动态生成随机颜色,并在 mouseenter 事件侦听器中检查该值是否为真,并生成那里的颜色。像这样的:

    let color = "";
    let psychColor = false;
    
    function createGrid(widthHeight) {
        document.getElementById(`grid-container`).innerHTML = "";
    
        for (let i = 0; i < widthHeight; i++) {
            let divRow = document.createElement(`div`);
            divRow.classList.add(`divRow`);
            document.getElementById(`grid-container`).appendChild(divRow);
            for (let y = 0; y < widthHeight; y++) {
                let divCol = document.createElement(`div`);
                divCol.classList.add(`divCol`);
                divRow.appendChild(divCol);
                divCol.addEventListener("mouseenter", function () {
                    if (psychColor) {
                        color = `#${randomColor()}`;
                    }
                    this.style.backgroundColor = color;
                });
            }
        }
    }
    
    createGrid(5);
    
    //black button
    document.getElementById(`black-button`).addEventListener(`click`, function () {
        psychColor = false;
        color = "black";
    });
    
    //psychedlic button selection
    document.getElementById(`psych-button`).addEventListener(`click`, function () {
        psychColor = true;
    });
    
    //returns random colors for psychedleic button
    function randomColor() {
        let randomColor = Math.floor(Math.random() * 16777215).toString(16);
        return randomColor;
    }
    

    【讨论】:

      猜你喜欢
      • 2014-11-13
      • 1970-01-01
      • 2013-05-18
      • 2020-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      相关资源
      最近更新 更多