JavaScript更改输入值时发生的事件?

JavaScript更改输入值时发生的事件?,javascript,events,Javascript,Events,当通过JavaScript代码更改元素的值时,会发生什么事件?例如: $input.value = 12; input事件在这里没有帮助,因为更改值的不是用户 在Chrome上测试时,不会触发change事件。可能是因为元素没有失去焦点(它没有获得焦点,所以它不能失去焦点)?一种可能的策略是使用a来检测属性中的更改,如下所示: var observer = new MutationObserver(function(mutations) { mutations.forEac

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

$input.value = 12;
input
事件在这里没有帮助,因为更改值的不是用户


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

一种可能的策略是使用a来检测属性中的更改,如下所示:

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
语句旁边的属性,就可以得到所需的结果。

我不认为有一个事件会覆盖输入的所有编程指定场景。但是,我可以告诉您,您可以通过编程“触发”事件(自定义事件、常规事件或仅触发事件处理程序)

在我看来,您正在使用jQuery,因此,您可以使用:

$('input#inputId').val('my new value...').triggerHandler('change');

在该示例中,您正在分配一个值,并强制调用绑定了“change”事件的处理程序。

没有用于该事件的内置事件。您至少有四种选择:

  • 无论何时在代码中更改
    $input.value
    ,都可以调用更改所触发的代码
  • 民意测验
  • 给自己一个方法来更改该值,该方法也会执行通知
  • (#3的变体)为自己提供一个用于更改值的属性,该属性也会执行通知
  • 其中,您将注意到#1、#3和#4都要求您在代码中执行与仅执行
    $input.value=“new value”不同的操作轮询选项#2是唯一可以直接设置
    值的代码

    详情:

  • 最简单的解决方案是:在代码中更改
    $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(函数(){
    var newValue=$input.value;
    如果(最后$inputValue!=新值){
    最后$inputValue=新值;
    handleValueChange();
    }
    }, 50); // 20次/秒
    函数handleValueChange(){
    log(“$input的值已更改:”+$input.value);
    }
    //触发变化
    setTimeout(函数(){
    $input.value=“新值”;
    }, 800);
    
    我会根据T.J.Crowder的建议添加第五个选项。 但是,不必添加新属性,您可以更改实际的“value”属性,以便在设置时触发额外的操作-对于特定的输入元素或所有输入对象:

    //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=“new value”。在输入框中键入新值时,它不起作用。

    基于@t-j-crowder和@maciej swist answers,让我们添加这一个,使用“.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);
    }
    

    下面是一个钩住所有输入的值属性更改的解决方案:

    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 + "\"");
    });
    

    一种简单的方法就是在更改值时触发输入事件

    您可以用普通javascript实现这一点

    在脚本的早期,将以下内容放在脚本中:

    let inputEvent = new Event('input',{bubbles:true,cancelable: true});
    
    您可以将“输入”更改为所需的事件,“更改”、“模糊”等

    然后,无论何时更改值,只要在同一元素上调用此事件即可

    input.value = 12;// <- your example
    input.dispatchEvent(inputEvent);// <- calling an event
    

    input.value=12;//当值被Javascript更改时没有事件。@Kinduser否…虽然存在一些异常,但事件大多是由于影响浏览器的外部操作而触发的,而不是来自Javascript代码。@Kinduser“否”是完整答案。我似乎找不到非jQuery副本,例如这是一个非常奇特的解决方案。实际上我需要反映外部的变化,这样才不会帮助我。但这仍然是一个很好的解决方案,它在chrome和firefox上都能运行。它们似乎也改变了dom中的值!聪明和有黑客感,我喜欢它,只是确保在调试时只使用它:)所有的要点是第三方更改了值不是我,而是谢谢你的建议