这篇文章发布于 2021年05月13日,星期四,20:17,归类于 JS实例 。 阅读 15535 次, 今日 5 次 7 条评论
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赋值时候的设置器函数,包含了浏览器原生的行为。属性描述符对象支持的属性和方法包括:
还有个类似的静态方法名为 Reflect.getOwnPropertyDescriptor(),大家有兴趣可以访问对应的MDN文档了解一番。
//zxx: 如果你看到这段文字,说明你现在访问是体验糟糕的垃圾盗版网站,你可以访问原文获得很好的体验:https://www.zhangxinxu.com/wordpress/?p=9949(作者张鑫旭)
四、不只是触发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对象实现类似的效果,这个之后有机会再介绍。
今天去医院拔了两颗智齿,半张脸都是麻的,现在拔牙位置还疼,疼到颌面骨都疼,好惨。
这回大家要真的心疼哥哥了,求分享求转发。
本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=9949(本篇完)
相关文章
- Proxy是代理,Reflect是干嘛用的? (0.696)
- JS CustomEvent自定义事件传参小技巧 (0.304)
- Safari不支持build-in自定义元素的兼容处理 (0.304)
- 聊聊JS DOM变化的监听检测与应用 (0.174)
- 漫谈js自定义事件、DOM/伪DOM自定义事件 (0.130)
这里的应该是this.dispatchEvent(new CustomEvent(‘change’));吧,本地试了试,两个input的时候,这儿是this才能两个input都监听到各自的change。
有没有办法通过set让input和其它dom实现绑定,而不通过change等事件呢。
简单说就是,input.value = ‘hello world’;然后div的文本就变成这个,不注册事件的情况下。
张鑫旭 more ,09年 华中科技大学 毕业,现 上海 ,就职于 阅文集团 ,专注 web前端 偏前领域,著有 《CSS世界》 《CSS选择器世界》 《CSS新世界》
今年热议
- 使用jsPDF导出PDF文件实践分享 (23)
- 做了个纯前端JPG/PNG尺寸缩放+压缩的在线工具 (23)
- 好奇心驱使下试验了chatGPT写CSS代码的能力 (17)
- 又get到了,JS复制图片到剪切板 (13)
- mp4box.js加WebCodecs 解码MP4视频帧并渲染 (13)
- CSS margin-trim属性是做什么用的? (13)
- 瞎折腾,使用JS让中文内容莫名其妙、狗屁不通 (12)
- CSS高宽不等图片固定比例布局的三重进化 (12)
- AI代码辅助工具codeium和copilot在前端表现对比 (9)
- JS audio加图片序列或canvas转webM/MP4的实现 (9)