动态更改复选框不会触发onChange事件?

11
注意:jQuery 不是一个选项。
我想检测复选框状态的变化,但当我尝试使用 onChange 事件时它似乎没有触发。
document.getElementById('myCheckBox').addEventListener('change',function() {
    console.log('Changed!');
});
document.getElementById('someLink').onClick = function() {
    // toggle checkbox
    document.getElementById('myCheckBox').checked = !document.getElementById('myCheckBox').checked;
};

当我点击#someLink时,change事件没有被触发。我可以为#myLink添加另一个监听器,但如果我添加其他链接来检查相同的框,则必须添加更多监听器。我想要一个复选框change事件的监听器。再次强调,jQuery不是选项,我需要vanilla JS。

编辑:如果我没有表述清楚,对不起,但我想避免在将检查此框的每个链接上添加复杂性。因此,理想情况下(也许答案是不可能的),我不想完全改变链接/单击逻辑。我希望能够在代码的任何地方更改.checked属性并在没有每次更改时增加其他逻辑的情况下进行检测(如果可能)。

更新:

好吧,显然没有办法在不更改onClick逻辑的情况下优雅地解决这个问题,因此(像某种动物一样),我最终通过以下方式强制解决了这个问题:

function mySentinel() {
    if(document.getElementById('myCheckBox').checked) {
        console.log("I've been checked!");
        return;
    }
    setTimeout("mySentinel()",100);
}
// then call this somewhere in the on document load section...
mySentinel();

如果你想的话,你可以添加某种形式的超时时间:

function mySentinel(var i) {
    if(document.getElementById('myCheckBox').checked) {
        console.log("I've been checked!");
        return;
    }
    if(i <= 0) {
        console.log("Time out. Still not checked");
    }
    i--;
    setTimeout("mySentinel("+i+")",100);
}
// then call this somewhere in the on document load section...
// 60 second timeout (some math can make the argument look nicer)
mySentinel(600);
4个回答

6

没错,通过编程更改输入的值或选中状态不会触发事件处理程序。

您需要使用JavaScript触发事件。

document.getElementById('myCheckBox').addEventListener('change',function() {
    console.log('Changed!');
});

document.getElementById('someLink').onclick = function() {
    var box = document.getElementById('myCheckBox')
    box.checked = !box.checked;

    if ("createEvent" in document) {
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent("change", false, true);
        box.dispatchEvent(evt);
    } else {
        box.fireEvent("onchange");
    }
};

请注意,它是 onclick(全部小写)

FIDDLE


编辑

我想避免为每个链接添加检查此框的复杂性。
所以理想情况下……我不想改变链接/单击逻辑。
我希望能够在代码中的任何位置更改 .checked 属性,并且在每次更改时无需添加其他逻辑即可检测到(如果可能)。

而这实际上是不可能的,除非使用间隔等可怕的黑客技巧。 当通过编程方式更改选中状态时,事件处理程序根本不会触发,因为在大多数情况下,这将是一个巨大的问题,并且要解决相反的情况要困难得多,即手动触发事件处理程序,这确实是唯一的方法。

当然,您可以使用类和外部函数等使其更方便。

document.getElementById('myCheckBox').addEventListener('change',function() {
    console.log('Changed!');
});

var links = document.querySelectorAll('.someLinkClass');

for (var i = links.length; i--;) {
    links[i].addEventListener('click', triggerChange, false);
}


function triggerChange() {
    var box = document.getElementById('myCheckBox')
    box.checked = !box.checked;

    if ("createEvent" in document) {
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent("change", false, true);
        box.dispatchEvent(evt);
    } else {
        box.fireEvent("onchange");
    }
};

每当您添加一个链接时,只需添加该类

<a href="#" class="someLinkClass">Change the checkbox</a>
<a href="#" class="someLinkClass">Change the checkbox again</a>
<a href="#" class="someLinkClass">Change the checkbox even more</a>

etc.


1
  1. 如果您想添加更多链接来触发复选框,请为它们创建一个类名称并使用 getElementByClass('classname')
  2. 在您的HTML中使用 onclick,而不是JS。示例: <div onclick="doSomething()"></div>
  3. 只需使用 if/else 语句进行选择 / 取消选择:

    
    if(document.getElementById('myCheck').checked){document.getElementById("myCheck").checked = false;} else{document.getElementById("myCheck").checked = true;}
    

我喜欢给每个链接添加一个类的想法。这可能是目前为止最干净的解决方案。它确实使每个链接变得更复杂,但是增加的复杂度非常小。 - user439299
你可以在一个对象上使用多个类,因此一个类可以专门用于样式,另一个类可以用于功能。例如:<div class="class1 class2"></div> - Mike K

0

-1

你可以调用/触发一个事件,但这并不像看起来那么容易,特别是当你需要处理Internet Explorer时。

最干净的解决方案是将你的事件放入自己的函数中,然后在需要的地方调用它。

function handleEvent(){
    console.log('Changed!');
}

documentent.getElementById('myCheckBox').addEventListener('change',function() {
    handleEvent()
});
document.getElementById('someLink').onClick = function() {
    // toggle checkbox
    document.getElementById('myCheckBox').checked = !document.getElementById('myCheckBox').checked;
    handleEvent();
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接