每次尝试动态填充 UI 的时间都会线性增加?

发布于 2025-01-11 17:13:14 字数 7123 浏览 0 评论 0原文

要求:

  1. 用户输入“容器数量”和“控件数量”。
  2. 随机输入元素(数字、复选框等)将被创建并在容器之间均匀分布。
  3. 当用户再次单击“创建”时,用户界面中显示的输入元素将被删除,并且将再次填充新的随机输入元素集。 示例 UI填充控件

问题: 每次我创建一组新的输入元素时,创建所需的时间都会线性增加到一个点,然后减少一点并再次增加 时间日志example

我使用下面的代码清空容纳容器的 div 并创建输入元素

清空整个 div

node.innerHTML = ""

创建带标签的数字控件

function createNumber(display) {
  let controlWrap = document.createElement("div");
  let label = document.createElement("label")
  let control = document.createElement("input")
  control.type = "number";
  label.append("Numeric Input");
  label.append(control);
  controlWrap.append(label);
  controlWrap.style.display = display;
  controlWrap.classList.add("ctrl");
  return controlWrap;
}

查找下面的完整代码,

//Constands
const CTRL_DISPLAY_TYPE = "block"

//Selection
const numOfContainers = document.querySelector("#numOfContainers");
const numOfControls = document.querySelector("#numOfControls");
const createContainersBtn = document.querySelector("#create");
const containerWrapper = document.querySelector(".containerWrapper");
const controlHeading = document.querySelectorAll(".ctrlHeading");

//Event Listeners
createContainersBtn.addEventListener("click",createContainers);
controlHeading.forEach(element => element.addEventListener("click"),expandControl);

//Support-functions
function createControl(newControlContainer){
    let newControlWrapper = document.createElement("div")
    newControlWrapper.classList.add("ctrlWrapper");

    let newControl = createNumber(CTRL_DISPLAY_TYPE);
    newControlWrapper.appendChild(newControl);
    newControlContainer.appendChild(newControlWrapper);

}

function createNumber(display){
    let controlWrap = document.createElement("div");
    let label = document.createElement("label")
    let control = document.createElement("input")
    control.type = "number";
    label.append("Numeric Input");
    label.append(control);
    controlWrap.append(label);
    controlWrap.style.display = display;
    controlWrap.classList.add("ctrl");
    return controlWrap;
}

function calculateControlPerContainer(numOfContainers,numOfControls,maxLimit){
    let controlsPerContainer = []
    let pendingControls = numOfControls%numOfContainers
    let controlPerContainerNum = Math.floor(numOfControls/numOfContainers)
    for (let i=0;i<numOfContainers;i++){
        if (pendingControls>0){
            newControlsPerContainer=controlPerContainerNum+1;
            controlsPerContainer.push(newControlsPerContainer);
            --pendingControls;
        }
        else{
            controlsPerContainer.push(controlPerContainerNum);
        }
    }
    return controlsPerContainer
}

function expandControl(event){
    const control = event.currentTarget.nextElementSibling;
    if (control.style.display === "none"){
        control.style.display = "block";
    }
    else {
        control.style.display = "none"
    }
}

//utility-functions
function removeChild(node){
    while(node.firstChild){
        node.removeChild(node.firstChild);
    }
}

function clearNodeData(node){
    node.innerHTML = ""
}

//main-Functions
function createContainers(event){
    console.time("Deleting controls");
    const controlsPerContainer = calculateControlPerContainer(parseInt(numOfContainers.value),parseInt(numOfControls.value));
    clearNodeData(containerWrapper);
    //removeChild(containerWrapper);
    console.timeEnd("Deleting controls");  
    console.time("populating controls");
    controlsPerContainer.forEach(num=>{        
        let newControlContainer = document.createElement("div")
        newControlContainer.classList.add("ctrlContainer");
        for(let j=0;j<num;j++){
            createControl(newControlContainer);
        }
        containerWrapper.appendChild(newControlContainer);
    }) 
    console.timeEnd("populating controls");   
}
* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
    border: 0;
    height:100%
}

.containerWrapper{
    display:flex;
    flex-direction: row;
    height: 90%;
}

.ctrlContainer{
    /* flex-grow:1; */
    flex-shrink: 0;
    border-style: solid;
    border-width: 0.5px;
    margin:0 2px;
    flex-basis: calc(25% - 4px);
    align-items: stretch;
    display:flex;
    flex-direction: column;
    overflow: auto;
}

.ctrlWrapper{
    border-style: solid;
    border-width: .5px;
    margin:2px
}

.ctrlHeading{
    display:block;
    width: 100%;
    text-align: left;
    border: 0;
}

.ctrl{
    display:none;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dynamic Controls</title>
    <link rel="stylesheet" href="style/main.css">
</head>
<body>
    <label for="numOfContainers">Number of Containers</label>
    <input type="number" id="numOfContainers" name="numOfContainers" min="1" max="500" value="100">
    <label for="numOfControls">Number of Controls</label>
    <input type="number" id="numOfControls" name="numOfControls" min="1" max="1500" value="1500"><br>
    <button id="create">Create</button>
    <div class="containerWrapper">
        <!-- <div class="ctrlContainer">
            <div class="ctrlWrapper">
                <button class="ctrlHeading">Checkbox</button>
                <input class="ctrl" type="checkbox">
            </div>
            <div class="ctrlWrapper">
                <button class="ctrlHeading">Checkbox</button>
                <input class="ctrl" type="checkbox">
            </div>
        </div>
        <div class="ctrlContainer">2</div>
        <div class="ctrlContainer">3</div> -->
    </div>
    <script type="module" src="scripts/MainBackup.js"></script>
</body>
</html>

我尝试使用 Chrome 开发人员工具进行分析,可以看到“附加”功能花费了更多的总时间。如果我在删除或添加控件时做错了什么,以及如何避免每次运行都会增加时间,请告诉我。

更多探索后的更多信息:

  1. 我仅在 Chrome 中看到此行为。在 Firefox 和 Edge 中,没有时间累积。 火狐浏览器: 时间在 firefox 中填充控件
  2. 这仅发生在我的系统中。其他人无法复制。
  3. 时间累积发生在代码部分,其中我将输入附加到标签以将其分配给输入而不使用 id。如果我直接将输入附加到容器中,则不会发生时间累积

Requirement:

  1. User will enter "Number of Containers" and "Number of Controls"
  2. Random input elements (numeric, checkbox, etc) will be created and equally distributed among the containers.
  3. When user clicks on "Create" again, the input elements shown in the UI will be deleted and new set of random input elements will be populated again.
    Sample UI with Controls Populated

Issue:
Every time I create new set of input elements, the time taken for creating increases linearly up to a point then decreases little and increases again
Time Log example

I use the below code to empty the div that accommodates the containers and create input elements

Emptying the overall div

node.innerHTML = ""

Creating a numeric control with label

function createNumber(display) {
  let controlWrap = document.createElement("div");
  let label = document.createElement("label")
  let control = document.createElement("input")
  control.type = "number";
  label.append("Numeric Input");
  label.append(control);
  controlWrap.append(label);
  controlWrap.style.display = display;
  controlWrap.classList.add("ctrl");
  return controlWrap;
}

Find the entire code below,

//Constands
const CTRL_DISPLAY_TYPE = "block"

//Selection
const numOfContainers = document.querySelector("#numOfContainers");
const numOfControls = document.querySelector("#numOfControls");
const createContainersBtn = document.querySelector("#create");
const containerWrapper = document.querySelector(".containerWrapper");
const controlHeading = document.querySelectorAll(".ctrlHeading");

//Event Listeners
createContainersBtn.addEventListener("click",createContainers);
controlHeading.forEach(element => element.addEventListener("click"),expandControl);

//Support-functions
function createControl(newControlContainer){
    let newControlWrapper = document.createElement("div")
    newControlWrapper.classList.add("ctrlWrapper");

    let newControl = createNumber(CTRL_DISPLAY_TYPE);
    newControlWrapper.appendChild(newControl);
    newControlContainer.appendChild(newControlWrapper);

}

function createNumber(display){
    let controlWrap = document.createElement("div");
    let label = document.createElement("label")
    let control = document.createElement("input")
    control.type = "number";
    label.append("Numeric Input");
    label.append(control);
    controlWrap.append(label);
    controlWrap.style.display = display;
    controlWrap.classList.add("ctrl");
    return controlWrap;
}

function calculateControlPerContainer(numOfContainers,numOfControls,maxLimit){
    let controlsPerContainer = []
    let pendingControls = numOfControls%numOfContainers
    let controlPerContainerNum = Math.floor(numOfControls/numOfContainers)
    for (let i=0;i<numOfContainers;i++){
        if (pendingControls>0){
            newControlsPerContainer=controlPerContainerNum+1;
            controlsPerContainer.push(newControlsPerContainer);
            --pendingControls;
        }
        else{
            controlsPerContainer.push(controlPerContainerNum);
        }
    }
    return controlsPerContainer
}

function expandControl(event){
    const control = event.currentTarget.nextElementSibling;
    if (control.style.display === "none"){
        control.style.display = "block";
    }
    else {
        control.style.display = "none"
    }
}

//utility-functions
function removeChild(node){
    while(node.firstChild){
        node.removeChild(node.firstChild);
    }
}

function clearNodeData(node){
    node.innerHTML = ""
}

//main-Functions
function createContainers(event){
    console.time("Deleting controls");
    const controlsPerContainer = calculateControlPerContainer(parseInt(numOfContainers.value),parseInt(numOfControls.value));
    clearNodeData(containerWrapper);
    //removeChild(containerWrapper);
    console.timeEnd("Deleting controls");  
    console.time("populating controls");
    controlsPerContainer.forEach(num=>{        
        let newControlContainer = document.createElement("div")
        newControlContainer.classList.add("ctrlContainer");
        for(let j=0;j<num;j++){
            createControl(newControlContainer);
        }
        containerWrapper.appendChild(newControlContainer);
    }) 
    console.timeEnd("populating controls");   
}
* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
    border: 0;
    height:100%
}

.containerWrapper{
    display:flex;
    flex-direction: row;
    height: 90%;
}

.ctrlContainer{
    /* flex-grow:1; */
    flex-shrink: 0;
    border-style: solid;
    border-width: 0.5px;
    margin:0 2px;
    flex-basis: calc(25% - 4px);
    align-items: stretch;
    display:flex;
    flex-direction: column;
    overflow: auto;
}

.ctrlWrapper{
    border-style: solid;
    border-width: .5px;
    margin:2px
}

.ctrlHeading{
    display:block;
    width: 100%;
    text-align: left;
    border: 0;
}

.ctrl{
    display:none;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dynamic Controls</title>
    <link rel="stylesheet" href="style/main.css">
</head>
<body>
    <label for="numOfContainers">Number of Containers</label>
    <input type="number" id="numOfContainers" name="numOfContainers" min="1" max="500" value="100">
    <label for="numOfControls">Number of Controls</label>
    <input type="number" id="numOfControls" name="numOfControls" min="1" max="1500" value="1500"><br>
    <button id="create">Create</button>
    <div class="containerWrapper">
        <!-- <div class="ctrlContainer">
            <div class="ctrlWrapper">
                <button class="ctrlHeading">Checkbox</button>
                <input class="ctrl" type="checkbox">
            </div>
            <div class="ctrlWrapper">
                <button class="ctrlHeading">Checkbox</button>
                <input class="ctrl" type="checkbox">
            </div>
        </div>
        <div class="ctrlContainer">2</div>
        <div class="ctrlContainer">3</div> -->
    </div>
    <script type="module" src="scripts/MainBackup.js"></script>
</body>
</html>

I tried analyzing using chrome developer tools and could see "append" function is taking more total time. Please let me know if I am doing something wrong in deleting or adding controls and how to avoid this time build up with every run.

More Information after some more exploration:

  1. I am seeing this behavior only in chrome. In firefox and edge, there is no time buildup.
    Firefox:
    Time for populating controls in firefox
  2. This occurs only in my system. Others are not able to replicate.
  3. The time build-up occurs in portion of code in which I append inputs to the label to assign it to the input without using id. If I directly append the input to container, the time buildup doesn't happen
    Appending input to label

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文