

输入框value属性赋值触发js change事件的实现
source link: https://www.zhangxinxu.com/wordpress/2021/05/js-value-change/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9949
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

一、原生的行为表现
例如有一个很普通的输入框,HTML代码如下所示:
<input id="input">
此时,用户输入内容,或者粘贴内容,或者拖拽内容到输入框,都会触发input事件,失焦后会触发change事件。
但是有一个是例外,那就是如果使用value属性赋值,无论是input事件还是change事件都不会触发。
input.value = '张鑫旭'; // 不会触发change事件
需要我们手动触发下change事件,示意:
input.value = 'zhangxinxu'; // 手动触发change事件 input.dispatchEvent(new CustomEvent('change'));
显然,这样的处理就很啰嗦,dispatchEvent
,CustomEvent
这样的API对不少开发者而言是陌生的。
那有没有办法直接value赋值也能触发change事件呢?
二、自定义value属性
我们组的XboxYan (严文彬)提供了一种解决方案,就是使用getOwnPropertyDescriptor
方法先把浏览器原生的value赋值方法存下来,然后重新自定义value赋值方法,在重新自定义的value属性的set方法中注入change事件的触发。
JS代码示意如下:
const props = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); Object.defineProperty(HTMLInputElement.prototype, 'value', { ...props, set (v) { let oldv = this.value; props.set.call(this, v); // 手动触发change事件 if (oldv !== v) { input.dispatchEvent(new CustomEvent('change')); } } });
我们不妨测试下,有如下HTML代码:
<input id="input"> <p id="result"></p>
然后我们绑定change事件,然后再执行value赋值方法,代码如下所示:
input.addEventListener('change', function () { result.innerHTML += this.value; }); input.value = 'zhangxinxu';
运行后可以看到下面截图所示的效果,p#result
元素内自动填充了 ‘zhangxinxu’ 这几个字符。
三、关于getOwnPropertyDescriptor
Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。
所谓自有属性,指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性。
属性描述符也是个对象,英文叫做property descriptor,属性描述符也包含访问访问器函数(getter)的get方法和获取设置器函数(setter)的set方法,因此,上一节示意代码中的props.set
其实指的就是浏览器原生的value赋值时候的设置器函数,包含了浏览器原生的行为。
属性描述符对象支持的属性和方法包括:
value 该属性的值。 get 获取该属性的访问器函数,没有返回undefined。 set 获取该属性的设置器函数,没有返回undefined。 writable 当且仅当属性的值可以被改变时为true。 configurable 当且仅当指定对象的属性描述可以被改变或者属性可被删除时,为true。 enumerable 当且仅当指定对象的属性可以被枚举出时,为 true。还有个类似的静态方法名为 Reflect.getOwnPropertyDescriptor(),大家有兴趣可以访问对应的MDN文档了解一番。
四、不只是触发change事件
getOwnPropertyDescriptor() 方法自定义value属性后,不仅可以用来触发change事件,我们还可以主动触发输入框元素的渲染。
例如LuLu UI Edge主题中的颜色选择输入框支持 #RRGGBBAA 颜色格式,如下图所示:

原生的color输入框在设置value属性值为#RRGGBB色值时会自动变色,但是这里的color-opacity输入框是自定义的,并不识别#RRGGBBAA色值,此时就需要对value属性进行处理,赋值的时候自动改变输入框的UI,其原理和上面触发change时间类似。
代码示意:
class Color extends HTMLInputElement { constructor () { super(); } ... } const props = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); Object.defineProperty(Color.prototype, 'value', { ...props, set (value) { let strValue = value; // 目前的颜色值 let strOldValue = this.value; // UI同步匹配 this.uiMatch(); // 赋值 props.set.call(this, strOldValue); // change事件触发 if (strOldValue && strValue != strOldValue) { this.dispatchEvent(new CustomEvent('change', { 'bubbles': true })); } } });
此时给输入框执行 input.value = '#EB46467D'
就可以看到UI变化了。
// zxx: 实际上上面色值不对,和设计不符,左上50%应该是纯色,而不是和黑色的混合色,我这几天抽空处理下。
除了Object.defineProperty方法,我们还可以使用Proxy对象实现类似的效果,这个之后有机会再介绍。
今天去医院拔了两颗智齿,半张脸都是麻的,现在拔牙位置还疼,疼到颌面骨都疼,好惨。
这回大家要真的心疼哥哥了,求分享求转发。

Recommend
-
14
UGUI研究院之自动触发UI的消息事件(二十) 雨松MOMO
-
15
【Android】长按连续触发事件的实现方法 项目中需要实现一个类似购物车数量的小组件,需要单击时增加数量,长按时可以连续增大,之前的代码实现效果不理想,google后得到一个解决方法,测试可...
-
6
对于由 ISDA 定义的标准 CDS ,有几类触发 CDS 的信用事件: 没有履行支付义务 拒绝或延期支付义务 构成违约的债务重组 但 CDS 合约中并不一定包含上述所有事项。比如一个主权没有「破产」的概念(没有主权破产法...
-
9
为什么在 JS 函数 / 类中以属性赋值形式无法覆写 Symbol.hasInstance ?本例默认使用最小环境,且 Symbol.hasInstance 没有被以任何形式事先进行覆写,仍是初始 [native code]。 覆写失败意味着 …
-
7
Chrome 89 更新事件触发顺序,导致99%的文章都错了(包括MDN)大家好,我是秋风。嗯...我又来了,这次又是在...楠溪和的讨论中产生的问题。那事情是怎么样的呢?最近...
-
3
ios上loadedmetadata 事件在用户播放时才触发导致audio duration获取不到的问题发布于 16 分钟前H5页面上一组音频,需要获取每个音频的时长,展示在页面上,尝试使...
-
11
福布斯:NFT有三种场景可能会触发应税事件 • 1 天前 《福布斯》于10月28日发文谈NFT税收问题。其中提到,尽管美国国税局(IRS)尚未发布任何NFT...
-
5
...
-
8
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11003 鑫空间-鑫生活 本文欢迎分享与聚合,全文转载...
-
6
js实现输入框赋值,实现输入框的内容通过控制台自动发送 作者: dreamfly 分类: javascript 发布时间: 2023-11-28 12:47 在开发Web应用程序时,...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK