$input.value = 12;
input
事件在这里并没有起到作用,因为改变值的不是用户。
在 Chrome 上进行测试时,change
事件没有被触发。可能是因为该元素没有失去焦点(它没有获得焦点,因此也无法失去焦点)?
$input.value = 12;
input
事件在这里并没有起到作用,因为改变值的不是用户。
在 Chrome 上进行测试时,change
事件没有被触发。可能是因为该元素没有失去焦点(它没有获得焦点,因此也无法失去焦点)?
这方面没有内置的事件。您至少有四个选择:
$input.value
时,调用您想要触发的代码需要注意的是,在上述四种方法中,#1、#3 和 #4 都需要您从简单的 $input.value = "new value";
这样的代码中做出一些更改。轮询(选项 #2)是唯一适用于直接设置 value
的代码的方法。
细节:
The simplest solution: Any time you change $input.value
in code, call the code you want triggered by the change:
$input.value = "new value";
handleValueChange();
Poll for changes:
var last$inputValue = $input.value;
setInterval(function() {
var newValue = $input.value;
if (last$inputValue != newValue) {
last$inputValue = newValue;
handleValueChange();
}
}, 50); // 20 times/second
Polling has a bad reputation (for good reasons), because it's a constant CPU consumer. Modern browsers dial down timer events (or even bring them to a stop) when the tab doesn't have focus, which mitigates that a bit. 20 times/second isn't an issue on modern systems, even mobiles.
But still, polling is an ugly last resort.
Example:
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">
Give yourself a function to set the value and notify you, and use that function instead of value
, combined with an input
event handler to catch changes by users:
$input.setValue = function(newValue) {
this.value = newValue;
handleValueChange();
};
$input.addEventListener("input", handleValueChange, false);
Usage:
$input.setValue("new value");
Naturally, you have to remember to use setValue
instead of assigning to value
.
Example:
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">
A variant on #3: Give yourself a different property you can set (again combined with an event handler for user changes):
Object.defineProperty($input, "val", {
get: function() {
return this.value;
},
set: function(newValue) {
this.value = newValue;
handleValueChange();
}
});
$input.addEventListener("input", handleValueChange, false);
Usage:
$input.val = "new value";
This works in all modern browsers, even old Android, and even IE8 (which supports defineProperty
on DOM elements, but not JavaScript objects in general). Of course, you'd need to test it on your target browsers.
But $input.val = ...
looks like an error to anyone used to reading normal DOM code (or jQuery code).
Before you ask: No, you can't use the above to replace the value
property itself.
Example:
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">
根据 @t-j-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);
}
//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);
可以不针对特定的输入元素更改“value”属性,而是可以通用地更改所有输入元素的值:
Object.defineProperty(HTMLInputElement.prototype, "value", descriptor);
这种方法仅适用于使用JavaScript更改值的情况,例如input.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修改输入值时触发事件?
我们可以使用事件触发和target.dispatchEvent来实现,详情请参见此question。
以下是文本输入框的示例:
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
。$('input#inputId').val('my new value...').triggerHandler('change');