问题描述
我们使用 Backbone + ReactJS bundle 构建客户端应用程序.严重依赖臭名昭著的 valueLink
,我们通过自己的包装器将值直接传播到模型,该包装器支持 ReactJS 接口进行双向绑定.
We use Backbone + ReactJS bundle to build a client-side app.Heavily relying on notorious valueLink
we propagate values directly to the model via own wrapper that supports ReactJS interface for two way binding.
现在我们遇到了问题:
我们有 jquery.mask.js
插件,它以编程方式格式化输入值,因此它不会触发 React 事件.所有这些都会导致模型从用户输入中接收未格式化的值,而从插件中错过格式化的值.
We have jquery.mask.js
plugin which formats input value programmatically thus it doesn't fire React events. All this leads to situation when model receives unformatted values from user input and misses formatted ones from plugin.
React 似乎有很多取决于浏览器的事件处理策略.有没有什么通用的方法可以触发特定 DOM 元素的更改事件,以便 React 听到它?
It seems that React has plenty of event handling strategies depending on browser. Is there any common way to trigger change event for particular DOM element so that React will hear it?
推荐答案
对于 React 16 和 React >=15.6
Setter .value=
没有像我们想要的那样工作,因为 React 库覆盖了输入值 setter,但我们可以直接在 input
作为上下文调用该函数.
Setter .value=
is not working as we wanted because React library overrides input value setter but we can call the function directly on the input
as context.
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(input, 'react 16 value');
var ev2 = new Event('input', { bubbles: true});
input.dispatchEvent(ev2);
对于 textarea 元素,您应该使用 HTMLTextAreaElement
类的 prototype
.
For textarea element you should use prototype
of HTMLTextAreaElement
class.
新的 codepen 示例.
仅适用于 React
使用 react-dom ^15.6.0
你可以在事件对象上使用 simulated
标志让事件通过
With react-dom ^15.6.0
you can use simulated
flag on the event object for the event to pass through
var ev = new Event('input', { bubbles: true});
ev.simulated = true;
element.value = 'Something new';
element.dispatchEvent(ev);
我用一个例子做了一个codepen
I made a codepen with an example
要了解为什么需要新标志,我找到了此评论 很有帮助:
To understand why new flag is needed I found this comment very helpful:
React 中的输入逻辑现在对更改事件进行重复数据删除,因此它们不会触发每个值不止一次.它侦听浏览器 onChange/onInput事件以及 DOM 节点值道具上的设置(当您更新值通过javascript).这意味着如果你手动更新输入的值 input.value = 'foo' 然后调度一个ChangeEvent with { target: input } React 将注册这两个集合和事件,看到它的值仍然是''foo',认为它是重复的事件并吞下它.
这在正常情况下工作正常,因为启动了真实"浏览器事件不会触发 element.value 上的设置.你可以保释这个逻辑是通过标记你用模拟触发的事件来秘密进行的flag 和 react 将始终触发事件.https://https://github.com/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128
This works fine in normal cases because a "real" browser initiated event doesn't trigger sets on the element.value. You can bail out of this logic secretly by tagging the event you trigger with a simulated flag and react will always fire the event. https://github.com/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128
这篇关于在react js中触发onchange事件的最佳方法是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!