js 改变change方法_关于JS更新input元素的value属性引发的狗血讨论

ad8e828ac1e4edb04995c358dfb1d0fa.png

来个面试题:

  1. 在浏览器中,对于input节点的用户输入,何时触发"change"事件呢?
  2. 在浏览器中,JS更新input的value属性,会触发"change"事件吗?
  3. 如果不会触发,请问为什么?有什么办法解决吗?

根据对上面问题的理解,我分为以下三个认知阶段:

第一阶段:读者只需要答案即可:

  1. 当input在用户输入后,节点失去焦点的时候触发”change"事件,并且在“input"事件之后;
  2. 如果读者没理解,可以看下面的代码;结论是:不会触发”change"事件
  3. 目前搜索到的W3C规范中,貌似没有这样的能力,包括:"MutationObserver";当然,如果开发者调用dispatchEvent的方式不算;

adfe731f7d695653c9df1dc6bde11d89.png

如果读者只在乎结论的话,就可以不往下看了;下面聊下W3C的定义;

第二阶段:W3C的规范约束:

大家是否好奇:JS更新input的value属性,为什么不触发"change"事件呢?

所以,我们来看下W3C是如何定义"change"事件的,下面摘自链接中:

The onchange event occurs when a control loses the input focus and its value has been modified since gaining focus. This attribute applies to the following elements:INPUT,SELECT, andTEXTAREA.

规范说:该事件源于input控件在用户操作后失去焦点并且value变化时触发;

另外,我们再看看W3C是如何定义value更新的行为的,下面摘自链接中:

value
On getting, return the current value of the element. On setting:
1. Let oldValue be the element 's value.
2. Set the element 's value to the new value.
3. Set the element 's dirty value flag to true.
4. Invoke the value sanitization algorithm, if the element 's type attribute's current state defines one.
5. If the element 's value (after applying the value sanitization algorithm) is different from oldValue, and the element has a text entry cursor position, move the text entry cursor position to the end of the text control, unselecting any selected text and resetting the selection direction to "none".

可以看到:其中并没有约定要触发"change"事件;

所以各类浏览器不触发事件是很正确的表现了;

如果读者只在乎W3C定义的话,就可以不往下看了;下面聊聊为什么;

第三阶段:为什么W3C这么定义;

大家是否好奇:JS更新input的value属性,W3C为什么不触发"change"事件呢?

有人说,W3C就是这么定义的啊!

实际上,我想问的是:为什么W3C这么定义呢

我觉得"change"事件这么定义在语义上有问题,如果不想有问题,那么办法有两种:

  1. JS更新,触发”change"事件;
  2. 将规范中的"change"事件名称,更名为:"userchange"或者"uachange";(ua代表user agent)

为什么说语义有问题,解释如下:

站在开发者的认知角度上,"change"代表的是一种"状态"的变化,它不在乎是"主动改变"还是"被动改变";主动为用户的输入改变,被动为代码层面的更新赋值;

按照正常人对上面"change"单词的语义理解,JS更新value,也属于一种状态change(更何况UI都会变化),就应该触发"change"事件才对;

带着这个疑问我问了一圈身边的开发者,有了下面的对话:

作者:问个问题:通过JS修改input的value值,为什么监听的input,change事件不会触发呢?为什么这么设计?
大壮:我理解的change事件应是在value只改变且失去焦点时才会触发,应该是从性能上考虑的吧
翠花:value的改变是事件触发的结果,如果变成原因是不是就死循环了
二壮:应该是避免事件冒泡导致不必要的性能损失吧,我猜的
W3C:When the change event applies, if the element does not have an activation behavior defined but uses a user interface that involves an explicit commit action, then any time the user commits a change to the element's value or list of selected files, the user agent must queue a task to fire a simple event that bubbles named change at the input element, then broadcast formchange events at the input element's form owner.
作者:Chrome源码没看到线索,查了W3C,我理解这么个意思:
change事件属于用户GUI操作产生的,对于通过JS改变的行为,不属于这类管理范围;
作者:我深深觉得这是web的坑,很早这种行为就定了,又没法兼容。你看Android就不是这种行为呀。从名字上来说,input事件不触发合理,change事件名,从直观理解就应该触发呀。js更新不算change?
对话:... 后面又聊到了"event loop"与异步机制,对话走偏了,就不扯了;

事实上,如果在Android平台中,通过代码修改,确实会触发类似的"textchanged"事件的;

由于两个平台表现不一致,没办法,在Github带着疑问去W3C问了;

老外效率真心高,第二天就回复了;

老外2:Unfortunately, we cannot change the names of events that have been dispatching for over two decades.

事实证明了我的看法,规范的原始定义造成了既成事实

如果硬要揪毛病,确实不合适;但是已经定义了20多年了,再改很容易不兼容!

好了,截止这里就结束了;之所以问这个问题,是因为快应用在设计的时候,就面临着:

到底遵守W3C规范(不触发),还是Android其它平台(触发)的行为;

个人看法,应该触发事件,不遵守规范;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值