基于对象状态在js/html中动态创建按钮

Dynamically create buttons in js/html based on object state

本文关键字:html 动态 按钮 创建 js 于对象 对象 状态      更新时间:2023-09-26

我有以下情况无法解决。我对js还比较陌生。我有一个在网页上运行的js。当按下KB快捷键时,脚本将运行。在修改了一些内容后,它会弹出一个html横幅,我想根据用户运行脚本的内容在其中放置某些消息和按钮。对于一个简单的情况,假设有两条潜在的消息可以进入这个弹出窗口。我在一个对象数组中有详细信息:

   NH_Bann = {
        STC: {
            active: false,
            bannText: "Force Title Case: ",
            id: "toTitleCaseStrong",
            value: "Yes",
            action: function() {
                var newNameStr = toTitleCaseStrong(vname);
                if (newNameStr !== name) {
                    //**update function
                    NH_Bann.STC.active = false;
                }
            }
        },
        DTC: {
            active: false,
            bannText: "Enable DTC? ",
            id: "addDTC",
            value: "Yes",
            action: function() {
                //**update function
                NH_Bann.DTC.active = false;
            }
        }
    }

当脚本运行时,有一些if语句可以将活动键更改为true。脚本运行后,我想运行NH_Bann中的对象,如果活动键为true,则生成一条带有触发操作按钮的操作按钮的消息。我遇到的问题是动态地制作按钮。从其他线程中,我认为我可以将按钮存储在一个数组中,但也许onclick不起作用?这就是我所拥有的:

function setupButtons() {
    var ixButt = 0;
    var btn = [];
    for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
        tempKey = Object.keys(NH_Bann)[NHix];
        if (NH_Bann[tempKey].active) {
            btn[ixButt] = document.getElementById(NH_Bann[tempKey].id); 
            btn[ixButt].onclick = function(){
                NH_Bann[tempKey].action();
                assembleBanner();  // makes the html for the banner
            } 
            ixButt++;
        }
    }
}

我在另一段设置ID的代码中制作按钮:

function assembleBanner() {
    sidebarMessageEXT = [sidebarMessage.slice(0)];
    var EXTOption = false;
    for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
        tempKey = Object.keys(NH_Bann)[NHix];
        if (NH_Bann[tempKey].active) {
            sidebarMessageEXT.push(NH_Bann[tempKey].bannText + '<input id="' + NH_Bann[tempKey].id + '" type="button" value="' + NH_Bann[tempKey].value + '">');
            EXTOption = true;
        }
    }
    if (EXTOption) {
        sidebarMessageEXT = sidebarMessageEXT.join("<li>");
        displayBanners(sidebarMessageEXT,severity);
        setupButtons();
    } else {
        displayBanners(sidebarMessage,severity);    
        setupButtons();
    }
}

我遇到的问题是,如果两个对象都是活动的==true,我会在标题中得到两条不同的消息和两个按钮,但按下它们总是会触发DTC对象的更新功能。有什么建议吗?我对其他方法持开放态度,但我需要能够随着时间的推移添加到对象列表中,并根据每个对象的活动键的状态有条件地显示按钮。Thx!

这个问题与闭包有关。在此代码中:

function setupButtons() {
    var ixButt = 0;
    var btn = [];
    for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
        tempKey = Object.keys(NH_Bann)[NHix];
        if (NH_Bann[tempKey].active) {
            btn[ixButt] = document.getElementById(NH_Bann[tempKey].id); 
            btn[ixButt].onclick = function(){
                NH_Bann[tempKey].action();
                assembleBanner();  // makes the html for the banner
            } 
            ixButt++;
        }
    }    
}

CCD_ 1是一个存在于对CCD_ 2的调用中的变量。请注意,您正在一个循环中创建两个onclick函数回调,它们都引用了tempKey。然而,他们不会引用函数创建时变量的值,而是引用变量的最新值。因此,一旦循环完成,tempKey将引用它所具有的上一个值。

要解决此问题,您可以使用此技巧为每个具有正确值的onclick创建闭包:

function setupButtons() {
    var ixButt = 0;
    var btn = [];
    for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
        tempKey = Object.keys(NH_Bann)[NHix];
        if (NH_Bann[tempKey].active) {
            btn[ixButt] = document.getElementById(NH_Bann[tempKey].id); 
            btn[ixButt].onclick = (function(buttonId) {
              return function() {
                NH_Bann[buttonId].action();
                assembleBanner();  // makes the html for the banner
              } 
            })(tempKey);
            ixButt++;
        }
    }    
}

本质上,这是通过将tempKey的当前值传递给一个立即执行的函数,将其绑定到一个新变量,因此两个onclick函数都不再引用在循环期间更改的变量。

对于一种不那么深奥的方法,你可以将每个按钮的创建转移到它自己的命名函数中,传递所需的数据:

function setupButtons() {
    var btn = [];
    for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++) {
        tempKey = Object.keys(NH_Bann)[NHix];
        if (NH_Bann[tempKey].active) {
            btn.push(setupButton(NH_Bann[tempKey]);
        }
    }    
}
function setupButton(bannerData) {
    var button = document.getElementById(bannerData.id);
    button.onclick = function() {
        bannerData.action();
        assembleBanner();
    };
    return button;
}