【问题标题】:Is there a way to listen to textbox when its value is changed programmatically当文本框的值以编程方式更改时,有没有办法收听文本框
【发布时间】:2017-11-26 06:20:33
【问题描述】:

环境:
只有 JavaScript(没有 jquery :( )
按钮单击事件处理程序不可更改。

如果文本框的值以编程方式更改,有没有办法收听文本框?

<input type="button" id="button1" value="button" />
<input type="text" id="text1" />


var btn1 = document.getElementById('button1');
var txt1 = document.getElementById('text1');
btn1.onclick=function(){ txt1.value = 'hello world'}

https://jsfiddle.net/yrt7e57w/

【问题讨论】:

  • txt.onchange=function(){}...
  • 我想我试过了,但它对我不起作用 - jsfiddle.net/yrt7e57w/1
  • 您是否尝试过使用添加事件功能并为其指定“更改”事件类型?
  • 请注意,您的示例安装了 onclick 监听器,而不是 onchange 监听器。
  • 程序化更改不会触发 onchange、onclick、onAnything——您必须对 Object 对象本身进行更改才能触发某些内容。看看stackoverflow.com/questions/19325938/…——可能重复。

标签: javascript


【解决方案1】:

您可以依靠编码人员以编程方式更改要知道的元素以触发 onChange,但这是一个不确定的提议。浏览其他帖子,这看起来很有希望:对于您的文本元素,覆盖 setter 和 getter,以便它们自动触发键控更改或编程更改。

var btn1 = document.getElementById('button1');
var txt1 = document.getElementById('text1');


btn1.onclick = function() {
    txt1.value = 'hello world'
  }
  
txt1.addEventListener("change", function(e){
  console.log(txt1.value);
})
  
  //property mutation for hidden input
Object.defineProperty(txt1, "value", {
  // Don't override the getter, but stub it in.
  get: function() {
    return this.getAttribute("value");
  },
  // In the setter, we want to set the value
  //  and also fire off the change event.
  //  By doing this, the coder changing the
  //  value never needs worry about it.
  set: function(val) {
    console.log("set");

    // handle value change here
    this.setAttribute("value", val);

    //fire the event
    if ("createEvent" in document) { //NON IE browsers
      var evt = document.createEvent("HTMLEvents");
      evt.initEvent("change", false, true);
      txt1.dispatchEvent(evt);
    } else { //IE
      var evt = document.createEventObject();
      txt1.fireEvent("onchange", evt);
    }
  }
});
<input type="button" id="button1" value="button" />
<input type="text" id="text1" />

或将其视为小提琴Here

因此,要回答您关于为什么单击处理程序将输入显示为具有空值的问题,这是因为 getter/setter 覆盖了默认值行为。解决这个问题的最简单方法是创建一个自定义 getter/setter 来充当 value 属性的接口:

var btn1 = document.getElementById('button1');
var txt1 = document.getElementById('text1');

btn1.onclick = function() {
  console.log("in the button's click handler, ");
  console.log("Value is: " + txt1.val);
  console.log("--------------------------------")
  txt1.val = 'hello world'
}

txt1.addEventListener("change", function(e) {
  console.log("in txt1.onChange function...")
  console.log(this.val);
  console.log("--------------------------------")
})


//property mutation for hidden input
Object.defineProperty(txt1, "val", {
  get: function() {
    return this.value;
  },
  set: function(val) {
    // handle value change here
    this.value = val;

    //fire the event
    if ("createEvent" in document) { //NON IE browsers
      var evt = document.createEvent("HTMLEvents");
      evt.initEvent("change", false, true);
      txt1.dispatchEvent(evt);
    } else { //IE
      var evt = document.createEventObject();
      txt1.fireEvent("onchange", evt);
    }
  }
});
<input type="button" id="button1" value="button" />
<input type="text" id="text1" />

这里发生的事情是,当单击按钮时,我获取输入的 val 属性(获取幕后的值),然后以编程方式设置同一输入的 val 属性(再次设置值属性)。出于某种原因,您不能在 object.defineProperty 中对输入的 value 属性使用 get/set 而不完全破坏它。所以在控制台中,你会看到三个函数调用:当你点击按钮时,输入失去焦点,触发它的改变方法,但是按钮本身触发它的点击处理程序,然后改变输入的值并触发再次更改处理程序。

希望这会有所帮助!

再次,将其视为fiddle...

【讨论】:

  • 奖励:如果我在文本中输入一些内容并尝试在第一次显示 null 时提醒它,您能否了解原因? jsfiddle.net/dyLb6543/1
  • @Rod,看看我的帖子的变化。它有点笨拙,因为它创建了一个自定义 val 属性来充当 value 属性的接口,但它工作得很好。
【解决方案2】:

当您以编程方式更改文本时,您可以使用element.dispatchEvent(event)。在您的示例中,它看起来像:

var btn1 = document.getElementById('button1');
var txt1 = document.getElementById('text1');

btn1.addEventListener("click", function() { // Add to OnClick of button.
    txt1.dispatchEvent(new Event('change')); // force change event to run on textbox.
});

txt1.addEventListener("change", function(e){ // EventListener for OnChange of the element.
    alert("changed");
});

addEventListener 本身不起作用,因为它并没有在 DOM 中完全改变。

以上是一个简单的解决方案,需要按几下按键,但要获得更易于维护和可重用的解决方案,请查看 Snowmonkey 的答案(可能还有该问题的大多数其他答案)https://stackoverflow.com/a/44708746/640263

【讨论】:

  • 在按钮单击处理程序之外工作的任何方式(该部分已密封)。对于没有提及这一点,我深表歉意。
  • 我已经更新了答案,您应该仍然可以通过addEventListenerclick 事件添加到元素。
  • 在我看来,文本元素本身应该负责触发 onchange —— 连接按钮和文本框之间的连接会增加一个可能不够灵活的硬依赖。
  • @Snowmonkey 我同意你的看法,如果你不使用任何类型的绑定框架,它可以让你更容易找到做什么,但它总是取决于需要做什么,所以在这种情况下,我认为这是最好的解决方案。
  • 看看我的——文本框本身正在监听变化,使用 Object.set,并在其自身上触发 onChange。因此它不关心是什么触发了变化,也不关心页面上的其他元素是什么,它只关心自己的业务。 ;)
【解决方案3】:

也许这是矫枉过正,
但你可以使用mutationObserver apilisten to an attribute change,
然后您必须通过setAttribute 方法更改值:

var btn1 = document.getElementById('button1');
var txt1 = document.getElementById('text1');

btn1.onclick=function(){ txt1.setAttribute('value', 'hello world') }

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log( mutation );
  });    
});
 
// configuration of the observer:
var config = {  attributes:true };
 
// pass in the target node, as well as the observer options
observer.observe(txt1, config);
<input type="button" id="button1" value="button" />
<input type="text" id="text1" />

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-13
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多