通过change事件,输入框可以感知用户手动输入,但是如果用程序对输入框进行赋值,则会出现无法感知的情况。
实践的HTML如下:
<input type="text" id="username" name="username"/>
实践的JS如下:
var username = document.querySelector("#username"),
counter = 0;
// 创建定时器对其进行设值
setInterval(function() {
// 强烈推荐使用这种方式赋值
username.setAttribute("value", counter++);
// 对输入框赋值
// username.value = counter ++;
}, 1000);
// 监听输入框的change事件
username.addEventListener("change", function() {
console.debug("change", this.value);
});
执行上面的代码,观察浏览器的控制台窗口,发现没有任何输出,也就是说对于程序设值的这种方式,输入框完全无法感知到变化。那使用focus与blur事件呢?
// 在设值时触发focus、blur事件
setInterval(function() {
username.focus();
// 强烈推荐使用这种方式赋值
username.setAttribute("value", counter++);
// 对输入框赋值
// username.value = counter ++;
username.blur();
}, 1000);
// 监听输入框的blur、focus事件
username.addEventListener("blur", function() {
console.debug("change", this.value);
});
执行的结果是,只能感知到很少的一部分状态变化(随机地有几次被感知到),所以这种办法不能被采用,因为必然会出现难以预料的bug。并且这种办法会在设值时侵入太多的代码,难以满足实际的情况,如第三方插件封装了某个输入框,我们想感知到此输入框内容的变化,如果采用上面的代码,则需要大量地修改第三方插件的代码。
经过仔细地研究,发现HTML5提供了一个新的观察接口Observer,可以用来观察DOM的子节点与属性的变化,实例如下:
// 定义观察器Observer
var observer = new MutationObserver(function() {
console.debug(username.value);
});
// 定义需要监控dom的哪些内容
observer.observe(username, {
attributes : true,
attributeOldValue : false,
attributeFilter : ['value']
characterData : true,
characterDataOldValue : true
});
现在观察浏览器的输出窗口,发现能观察到每一次值的改变。但需要特别注意的是,赋值的方式一定要采用setAttribute方式,赋值的方式一定要采用setAttribute方式,赋值的方式一定要采用setAttribute方式。(重要的事情说三遍)