【问题标题】:Detect programmatic changes on input type text检测输入类型文本的编程更改
【发布时间】:2021-09-09 15:22:45
【问题描述】:

有没有办法在脚本更改输入类型文本的值时获得通知。

我有

<input id='test' type='text' />

还有一个脚本

document.getElementById('test').value = 'bbb'; 

我希望收到有关文本更改的通知。

我知道我可以通过 keydown、keyup、onblur 等通知我(如果我试图跟踪用户输入,这会起作用)但是如果以编程方式完成更改呢?

非常感谢

附言 请不要使用 JQuery,或者如果 jquery 可以,有人可以解释它是如何实现的。

【问题讨论】:

  • 在脚本中调用 document.getElementById('test').value = 'bbb';你不调用函数
  • @555k 我必须注册什么?例如,如果我输入 document.getElementById('test').onkeyup = function () { ... } 那将不起作用
  • 一个想法是从 DOMElement 中“继承”,用 getter 和 setter 定义一个“值”-属性(如@MaxArt 建议的那样),并在 getter 和 setter 内部使用原始“值”- DOMElement 的属性。
  • @Zo72 你对这个问题做了什么,你接受了什么

标签: javascript html


【解决方案1】:

如果您使用的是现代浏览器,您可以尝试以下方式:

var input = document.getElementById('test');
input._value = input.value;
Object.defineProperty(input, "value", {
    get: function() {return this._value;},
    set: function(v) {
        // Do your stuff
        this._value = v;
    }
});

如果您实际上不期望任何用户输入(即隐藏类型输入字段),则此解决方案很好,因为它极具破坏性 DOM 基本功能。请记住这一点。

【讨论】:

  • 似乎当您重新定义value-属性时,输入字段不再“连接”到value-属性。
  • @MaxArt 真的很聪明……但是有副作用吗?我有点担心重新定义“价值”属性
  • @Zo72 副作用主要是 Jasd 提到的,另外还有一个问题是,如果用户输入一个新值,没有办法你可以检测到他输入的内容,除非您将捕获每一个关键事件并对其进行解释。这已经是一团糟了,但如果你添加剪切/复制/粘贴事件,它会变得很大。
  • @MaxArt 我非常喜欢它。我只是希望有人已经这样做了,并且有一个 github sn-p。这似乎是相当低级的东西。我会做并测试它,如果它有效,我会标记最佳答案
  • 谢谢!它就像一个魅力。我仅使用它来确定哪个脚本更改了输入值。 set: function(v) { console.log('input value changed to',v); console.trace(); this._value = v; }
【解决方案2】:

我发现最简单的方法是手动触发事件:

document.getElementById('test').value = 'bbb';
var evt = new CustomEvent('change');
document.getElementById('test').dispatchEvent(evt);

当以编程方式更改值时,仅收听change 事件很容易出错。但是由于您要更改值,因此添加两行并使用 CustomEvent 触发更改事件。

那么您将能够捕捉到这个 change 事件,无论是内联:

<input id="test" onchange="console.log(this)">

或与听众一起:

document.getElementById('test').addEventListener('change',function(event) {
    console.log(event.target);
});

这样做的好处是,如果您有一个可由用户更改的输入,您可以捕获这两个事件(来自用户或脚本)

然而,这取决于您自己以编程方式更改输入值的事实。如果您使用的库(例如 datepickr)会更改您的输入值,您可能需要进入代码并将这两行添加到正确的位置。

现场演示:

// input node reference
const inputElem = document.querySelector('input')

// bind "change" event listener
inputElem.addEventListener('change', e => console.log(e.target.value))

// programatically change the input's value every 1 second
setInterval(() => { 
  // generate random value
  inputElem.value = Math.random() * 100 | 0; 
  
  // simulate the "change" event
  var evt = new CustomEvent('change')
  inputElem.dispatchEvent(evt)
}, 1000);
&lt;input&gt;

【讨论】:

  • 这不起作用,所以我错过了什么?如果用户打开控制台并执行$0.value = "asd"(参见$0),那么这如何捕获change?我们是否请用户触发更改事件? :)
  • @akinuri 我相信你有点误会了。在输入普通文本输入的上下文中提到了用户:“I know I could be notified by keydown,keyup, onblur etcetera (which works if I am trying to track user typing) but what about if the change is done programmatically ?”。这些事件是与文本输入交互时触发的正常事件。接受的答案也将其视为用户与正常输入进行交互。接受的答案和我的答案都涵盖了最终用户输入输入以及程序更改。
  • 我认为我们不同的地方在于,我假设程序更改源自编写脚本的程序员,而您认为程序更改源自用户浏览网页。
  • 这是最好的答案!我已经找了几个月了!
  • 问题是当你想检测代码中的值变化时你不是的作者,所以你不能简单地在值变化时触发一个假事件,而必须以某种方式检测它。 (我有一个需要检测此类东西的 3rd-party 插件)
猜你喜欢
  • 2011-09-03
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 2014-02-13
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
相关资源
最近更新 更多