我想知道如何检测html复选框输入的更改,即使它以编程方式更改,如下所示:
checkboxDomNode.checked = true
浏览器显然知道它已更改,因为它获得了可视化的标记,并且任何:checked
css伪类都被触发。我实际上是试图在javascript中模拟:checked
css伪类,这就是为什么我要找到一种强有力的方法来实现这一点。
我已经测试了“更改”事件,并且不会像上面那样在程序化更改中触发。它看起来像MutationObserver不支持对该属性所做的更改。
答案 0 :(得分:1)
Alan Darmasaputra答案的一个小扩展:您可以为每个更改执行两个任务,而不是为您的复选框使用简单的对象包装器,并为您的属性使用getter和setter:
var checkboxObject = {
node: document.querySelector('input[type=checkbox]'), // or whatever query you wish to perform
get checked() {
return this.node.checked;
},
set checked(value) {
var oldValue = this.node.checked;
this.node.checked = !!value;
if(oldValue !== !!value) {
this.node.dispatchEvent(new Event("change"));
}
}
};
checkboxObject.node.addEventListener('change',function(event){
//do something
});
// calls checkboxObject[get checked]
var state = checkboxObject.checked;
// calls checkboxObject[set checked] with argument 'false'
checkboxObject.checked = false;
正如您所看到的,这需要一些初始配置,但是您可以以编程方式更改已检查状态,并在一个分配中分派事件。
更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set
工作小提琴:
var checkboxObject = {
node: document.querySelector('input[type=checkbox]'), // or whatever query you wish to perform
get checked() {
return this.node.checked;
},
set checked(value) {
var oldValue = this.node.checked;
this.node.checked = !!value;
if(oldValue !== !!value) {
this.node.dispatchEvent(new Event("change"));
}
}
};
document.getElementById('check').addEventListener('click', function() {
checkboxObject.checked = true;
});
document.getElementById('uncheck').addEventListener('click', function() {
checkboxObject.checked = false;
});
checkboxObject.node.addEventListener('change',function(event){
document.getElementById('log').innerText += 'checkbox value changed! New value: ' + event.target.checked + '\n';
});
// Why implementing this directly on the checkbox element is not a good idea:
console.log( Object.getOwnPropertyDescriptor( Object.getPrototypeOf(checkboxObject.node), 'checked' ));

<button id="check">check</button>
<button id="uncheck">uncheck</button>
<input type="checkbox">
<div id="log" style="white-space: pre-line"></div>
&#13;
**编辑:**
直接在checkbox元素上实现此行为不是一个好主意。使用Object.getOwnPropertyDescriptor
,我们可以检查属性的类型(accessor descriptor
或data descriptor
)。如果我们对checkboxObject.node
的原型的checked属性执行此操作,如下所示:
console.log( Object.getOwnPropertyDescriptor( Object.getPrototypeOf(checkboxObject.node), 'checked' ));
输出将是:
{
"get": function () { [native code] },
"set": function () { [native code] },
"enumerable": true,
"configurable": true
}
这意味着该元素已经在其原型中为属性checked
定义了一个getter和setter。你可以在Object.getPrototypeOf()
你的复选框中实现逻辑,并明确地调用它上面的setter来调用本机行为,但这会让事情很难真正理解,特别是因为你必须将上下文绑定为该调用的checkbox元素。我会让你做出决定。
还要记住,现有的(原型)描述符可能是不可写的(在这种情况下它不是,否则它将在上面的输出中),这意味着覆盖这个的正常属性赋值将失败。在这种情况下,您必须直接在复选框元素上Object.defineProperty()
,以确保您实际上并未尝试覆盖不可变的原型设置者/获取者。
答案 1 :(得分:0)
为什么不使用 AngularJS 或 KnockoutJS 等任何java脚本框架尝试双向绑定。您也可以使用纯javaScript来完成它。
看看这篇文章,
http://www.lucaongaro.eu/blog/2012/12/02/easy-two-way-data-binding-in-javascript/
使用 AngularJS
的简单示例HTML:
<div ng-controller="checkCtrl">
Check It : <input type="checkbox" id="chkbox" ng-model="checked" />
<p ng-model="checked">{{checked}}</p>
</div>
AngularJS:
var testApp = angular.module("testApp", []);
testApp.controller("checkCtrl", function($scope){
$scope.checked = true;
});
答案 2 :(得分:0)
以编程方式修改的属性不会触发事件。您可以尝试添加onchange侦听器
checkboxDomNode.addEventListener('change',function(event){
//do something
})
然后在修改您的属性后,触发事件
checkboxDomNode.dispatchEvent(new Event("change"))
在Chrome 53上测试