[英]Event when input value is changed by JavaScript?
当<input>
元素的值通过 JavaScript 代码更改时会发生什么事件? 例如:
$input.value = 12;
input
事件在这里没有帮助,因为改变值的不是用户。
在 Chrome 上测试时,不会触发change
事件。 也许是因为元素没有失去焦点(它没有获得焦点,所以它不能失去焦点)?
没有内置事件。 你至少有四个选择:
$input.value
更改代码中的$input.value
时,调用您希望由更改触发的代码其中,您会注意到 #1、#3 和 #4 都要求您在代码中执行与$input.value = "new value";
轮询,选项#2,是唯一一种可以直接设置value
代码。
细节:
最简单的解决方案:任何时候在代码中更改$input.value
时,调用您希望由更改触发的代码:
$input.value = "new value"; handleValueChange();
投票更改:
var last$inputValue = $input.value; setInterval(function() { var newValue = $input.value; if (last$inputValue != newValue) { last$inputValue = newValue; handleValueChange(); } }, 50); // 20 times/second
轮询的名声很差(有充分的理由),因为它是一个持续的 CPU 消耗者。 当标签没有焦点时,现代浏览器拨打定时器事件(甚至将它们带到停止),这会减轻一点。 20 次/秒在现代系统甚至移动设备上都不是问题。
但是,投票仍然是一个丑陋的最后手段。
例子:
var $input = document.getElementById("$input"); var last$inputValue = $input.value; setInterval(function() { var newValue = $input.value; if (last$inputValue != newValue) { last$inputValue = newValue; handleValueChange(); } }, 50); // 20 times/second function handleValueChange() { console.log("$input's value changed: " + $input.value); } // Trigger a change setTimeout(function() { $input.value = "new value"; }, 800);
<input type="text" id="$input">
给自己一个函数来设置值并通知你,并使用该函数而不是value
,结合input
事件处理程序来捕获用户的更改:
$input.setValue = function(newValue) { this.value = newValue; handleValueChange(); }; $input.addEventListener("input", handleValueChange, false);
用法:
$input.setValue("new value");
当然,您必须记住使用setValue
而不是分配给value
。
例子:
var $input = document.getElementById("$input"); $input.setValue = function(newValue) { this.value = newValue; handleValueChange(); }; $input.addEventListener("input", handleValueChange, false); function handleValueChange() { console.log("$input's value changed: " + $input.value); } // Trigger a change setTimeout(function() { $input.setValue("new value"); }, 800);
<input type="text" id="$input">
#3 的变体:给自己一个可以设置的不同属性(再次结合用户更改的事件处理程序):
Object.defineProperty($input, "val", { get: function() { return this.value; }, set: function(newValue) { this.value = newValue; handleValueChange(); } }); $input.addEventListener("input", handleValueChange, false);
用法:
$input.val = "new value";
这适用于所有现代浏览器,甚至是旧的 Android,甚至 IE8(它支持 DOM 元素上的defineProperty
,但一般不支持 JavaScript 对象)。 当然,您需要在目标浏览器上对其进行测试。
但是$input.val = ...
对于习惯于阅读普通 DOM 代码(或 jQuery 代码)的任何人来说,这似乎是一个错误。
在你问之前:不,你不能用上面的来替换value
属性本身。
例子:
var $input = document.getElementById("$input"); Object.defineProperty($input, "val", { get: function() { return this.value; }, set: function(newValue) { this.value = newValue; handleValueChange(); } }); $input.addEventListener("input", handleValueChange, false); function handleValueChange() { console.log("$input's value changed: " + $input.value); } // Trigger a change setTimeout(function() { $input.val = "new value"; }, 800);
<input type="text" id="$input">
基于@tj-crowder 和@maciej-swist 的答案,让我们添加这个,使用“.apply”函数防止无限循环而不重新定义对象。
function customInputSetter(){
var descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value");
var originalSet = descriptor.set;
// define our own setter
descriptor.set = function(val) {
console.log("Value set", this, val);
originalSet.apply(this,arguments);
}
Object.defineProperty(HTMLInputElement.prototype, "value", descriptor);
}
我会根据 TJ Crowder 的建议添加第 5 个选项。 但不是添加新属性,您可以更改实际的“值”属性以在设置时触发其他操作 - 无论是针对特定输入元素,还是针对所有输入对象:
//First store the initial descriptor of the "value" property:
var descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value");
var inputSetter = descriptor.set;
//Then modify the "setter" of the value to notify when the value is changed:
descriptor.set = function(val) {
//changing to native setter to prevent the loop while setting the value
Object.defineProperty(this, "value", {set:inputSetter});
this.value = val;
//Custom code triggered when $input.value is set
console.log("Value set: "+val);
//changing back to custom setter
Object.defineProperty(this, "value", descriptor);
}
//Last add the new "value" descriptor to the $input element
Object.defineProperty($input, "value", descriptor);
不是更改特定输入元素的“值”属性,而是可以对所有输入元素进行一般更改:
Object.defineProperty(HTMLInputElement.prototype, "value", descriptor);
此方法仅适用于使用 javascript 更改值,例如 input.value="new value"。 在输入框中键入新值时不起作用。
这是挂钩所有输入更改的 value 属性的解决方案:
var valueDescriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value");
HTMLInputElement.prototype.addInputChangedByJsListener = function(cb) {
if(!this.hasOwnProperty("_inputChangedByJSListeners")) {
this._inputChangedByJSListeners = [];
}
this._inputChangedByJSListeners.push(cb);
}
Object.defineProperty(HTMLInputElement.prototype, "value", {
get: function() {
return valueDescriptor.get.apply(this, arguments);
},
set: function() {
var self = this;
valueDescriptor.set.apply(self, arguments);
if(this.hasOwnProperty("_inputChangedByJSListeners")){
this._inputChangedByJSListeners.forEach(function(cb) {
cb.apply(self);
})
}
}
});
用法示例:
document.getElementById("myInput").addInputChangedByJsListener(function() {
console.log("Input changed to \"" + this.value + "\"");
});
一种可能的策略是使用一个mutationObserver来检测属性的变化,如下所示:
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(){
console.log('hello')});
});
observer.observe($input, {
attributes: true
});
虽然这本身不会检测到如下变化:
$input.value = 12
它会检测到实际值属性的变化:
$input.setAttribute('value', 12)
因此,如果是您以编程方式设置值,只需确保在value = 12
语句旁边更改属性,您就可以获得所需的结果。
一种简单的方法是在更改值时触发输入事件。
你可以用普通的 javascript 来做到这一点。
在脚本的早期,输入如下内容:
let inputEvent = new Event('input',{bubbles:true,cancelable: true});
您可以将“输入”更改为您想要的事件、“更改”、“模糊”等
然后,任何时候你改变一个值,只需在同一个元素上调用这个事件
input.value = 12;// <- your example
input.dispatchEvent(inputEvent);// <- calling an event
这是香草javascript
我认为没有一个事件可以涵盖所有以编程方式分配的输入场景。 但是,我可以告诉您,您可以以编程方式“触发”事件(自定义事件、常规事件或仅触发事件处理程序 [s])
在我看来,您正在使用 jQuery,因此,您可以使用:
$('input#inputId').val('my new value...').triggerHandler('change');
在该示例中,您正在分配一个值,并强制调用与“更改”事件绑定的处理程序(或多个处理程序)。
JavaScript 更改输入值时的事件?
我们可以将事件触发与target.dispashEvent一起使用,如本问题所述。
文本输入示例:
const input = document.querySelector('.myTextInput');
//Create the appropriate event according to needs
const change = new InputEvent('change');
//Change the input value
input.value = 'new value';
//Fire the event;
const isNotCancelled = input.dispatchEvent(change);
当该事件类型的任何处理程序不使用event.preventDefault()
, isNotCancelled
将为true
,否则为false
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.