检测由JS引起的HTML对象更改

时间:2016-03-18 13:44:47

标签: javascript javascript-events

假设我有public final class MyRunnable { private static final int READY_TO_START = 0; private static final int ACTIVE = 1; private static final int STOPPED = 2; private final AtomicInteger status = new AtomicInteger(READY_TO_START); public void start() { if (!status.compareAndSet(READY_TO_START, ACTIVE)) { throw new IllegalStateException("Already started"); } // My one-time start code. } public void stop() { if (!status.compareAndSet(ACTIVE, STOPPED)) { throw new IllegalStateException("Can't stop, either not started or already stopped"); } // My one-time stop code. } } 。 我有一个 <DataGrid x:Name="CellStyleGrid" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="309,50,0,0" IsReadOnly="False" IsEnabled="True" CanUserAddRows="True" Width="172" RenderTransformOrigin="0.501,0.477" SelectionUnit="Cell" Grid.ColumnSpan="2" AlternatingRowBackground="#C2C2C2" AlternationCount="2" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Path=col1}" ClipboardContentBinding="{x:Null}" Header="Col1" CanUserResize="True"/> <DataGridTextColumn Binding="{Binding Path=col2}" ClipboardContentBinding="{x:Null}" Header="Col2" CanUserResize="True"/> <DataGridTextColumn Binding="{Binding Path=col3}" ClipboardContentBinding="{x:Null}" Header="Col3" CanUserResize="True"/> </DataGrid.Columns> <DataGrid.ColumnHeaderStyle> <Style TargetType="{x:Type DataGridColumnHeader}"> <Setter Property="Background" Value="#3B3B3B"/> <Setter Property="Foreground" Value="White"/> </Style> </DataGrid.ColumnHeaderStyle> </DataGrid> eventListener。

它会检测用户造成的所有更改:使用鼠标和键盘。但如果我会做这样的事情:

<select id='test'>

更改事件不会连线。

问题:

  1. onchange事件正在寻找什么,什么时候发生?
  2. 如何在没有间隔的情况下检测来自JS代码的更改?
  3. (我是对的:当我更改JS值时,document.getElementByID('test').value = 'new value'; 事件没有连线,因为没有创建change对象吗?)

1 个答案:

答案 0 :(得分:3)

<块引用>
  1. ChangeEvent 在什么时候触发? / 它是如何“从内部”运作的?

change 事件(注意没有 ChangeEvent 接口)就像任何事件一样,不看任何东西。事件由各种算法fired直接作为这些算法的一部分。

对于具有“文本”类型的输入,触发更改事件的算法是 here

当前读取

<块引用>

对于没有定义输入激活行为的输入元素,但这些事件适用,并且用户界面涉及交互式操作和显式提交操作,那么当用户更改元素的值时,用户代理必须排队用户交互任务源上的元素任务给定 input 元素以在 input 元素触发名为 input 的事件,气泡和组合属性初始化为 true,并且任何时候用户提交更改,用户代理都必须将元素排队给定 input 元素的用户交互任务源上的 task 以在 input 元素触发名为 change 的事件,并且气泡属性初始化为 true。

一些其他类型的输入确实有不同的算法,由它们的 input activation behavior 定义。


<块引用>
  1. 我是否能够检测到从 JS 代码中无间隔地触发的更改?

当然,您的代码进行了这些更改,您当然可以在更改的地方挂钩回调。
现在,出于调试目的,您可以覆盖输入的 value 属性,以便它在设置值时调用您的回调:

{
  const inp = document.querySelector("input");
  const original_desc = Object.getOwnPropertyDescriptor( HTMLInputElement.prototype, "value");
  const new_desc = Object.assign( {}, original_desc, {
    set(val) {
      console.log( "value just changed programmatically:", val );
      return original_desc.set.call( this, val );
    }
  } );
  Object.defineProperty( inp, "value", new_desc );
}

document.querySelector("button").onclick = () => {
  document.querySelector("input").value = "foo";
};
<input>
<button>change value programmatically</button>

但实际上,您必须求助于这种黑客手段,这意味着您需要解决一个更大的设计问题。


<块引用>
  1. 正如我发现的那样,当从代码更新值时,ChangeEvent 不会本机触发,因为没有创建 Event 对象。为什么设计成这样?

因为 change 事件,就像 input 一样,“被触发以表明用户已经与控件交互。source

作为网络作者,您可以控制在您的页面上运行的脚本,因此为您的脚本自行执行的操作触发事件是没有意义的,它应该能够触发此事件本身。