惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Microsoft Azure Blog
Microsoft Azure Blog
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
小众软件
小众软件
F
Fortinet All Blogs
Microsoft Security Blog
Microsoft Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Hackread – Cybersecurity News, Data Breaches, AI and More
量子位
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
aimingoo的专栏
aimingoo的专栏
B
Blog RSS Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
宝玉的分享
宝玉的分享
有赞技术团队
有赞技术团队
J
Java Code Geeks
WordPress大学
WordPress大学
The Cloudflare Blog

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活
输入框value属性赋值触发js change事件的实现 « 张鑫旭-鑫空...
张鑫旭,zhangxinxu · 2021-05-13 · via 张鑫旭-鑫空间-鑫生活

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'));

显然,这样的处理就很啰嗦,dispatchEventCustomEvent这样的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文档了解一番。

//zxx: 如果你看到这段文字,说明你现在访问是体验糟糕的垃圾盗版网站,你可以访问原文获得很好的体验:https://www.zhangxinxu.com/wordpress/?p=9949(作者张鑫旭)

四、不只是触发change事件

getOwnPropertyDescriptor() 方法自定义value属性后,不仅可以用来触发change事件,我们还可以主动触发输入框元素的渲染。

例如LuLu UI Edge主题中的颜色选择输入框支持 #RRGGBBAA 颜色格式,如下图所示:

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 &amp;&amp; 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

(本篇完)