繁体   English   中英

JavaScript 更改输入值时的事件?

[英]Event when input value is changed by JavaScript?

<input>元素的值通过 JavaScript 代码更改时会发生什么事件? 例如:

$input.value = 12;

input事件在这里没有帮助,因为改变值的不是用户。

在 Chrome 上测试时,不会触发change事件。 也许是因为元素没有失去焦点(它没有获得焦点,所以它不能失去焦点)?

没有内置事件。 你至少有四个选择:

  1. $input.value更改代码中的$input.value时,调用您希望由更改触发的代码
  2. 投票更改
  3. 给自己一个你用来改变值的方法,它也会做通知
  4. (#3 的变体)给自己一个用于更改值的属性,该属性也将发出通知

其中,您会注意到 #1、#3 和 #4 都要求您在代码中执行与$input.value = "new value"; 轮询,选项#2,是唯一一种可以直接设置value代码。

细节:

  1. 最简单的解决方案:任何时候在代码中更改$input.value时,调用您希望由更改触发的代码:

     $input.value = "new value"; handleValueChange();
  2. 投票更改:

     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">

  3. 给自己一个函数来设置值并通知你,并使用该函数而不是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">

  4. #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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM