onpropertychange,一个被现代前端遗忘的IE事件,为什么还值得我认真聊聊

admin

大家好,我是你们的老朋友,一个常年在代码、选题和咖啡之间反复横跳的自媒体作者,今天想聊一个听起来特别“上古”的词——onpropertychange,年轻一点的前端朋友可能看到这个词的第一反应是:这是啥?拼写检查都救不了它,可如果你维护过老系统,尤其是那些还跑在IE里的后台,你大概率被它折磨过,也被它救过。

先把话说清楚:onpropertychange 是IE浏览器里的一个专有事件,它的作用很直白——当某个DOM元素的属性发生变化时触发,value、className、disabled 等属性被修改,很多人当年用它来监听输入框内容变化,因为低版本IE里没有现在这么顺手的 input 事件,或者兼容性没这么统一。onpropertychange 就成了不少老项目里的“实时监听神器”。

我为什么突然想起它?因为前段时间帮一个朋友收拾他们单位的老后台,那是一个选课/报名类的系统,页面风格大概停留在“能用就行”的年代,浏览器还必须用IE,里面有个输入框,学生输入姓名时要实时显示匹配结果,旁边还有字数统计,现代前端写这个太简单了,addEventListener('input', fn) 一把梭,但那个项目里,代码写的是:

input.attachEvent('onpropertychange', function (e) {
  if (e.propertyName === 'value') {
    // 更新列表、统计字数
  }
});

我当时第一反应是:嚯,考古现场,第二反应是:还真不能随便删,因为那个环境里,input 事件不一定靠得住,onpropertychange 反而是最稳的,可问题也来了,这个事件太“敏感”了,你改 value 它触发,你改 className 它也触发,甚至你在回调里为了高亮改了个样式,它都可能再跑一遍,稍不注意就递归到页面卡死,那天我盯着控制台,感觉自己不是在修代码,是在安抚一个脾气古怪的老门铃:有人路过它响,风吹一下它也响。

这就是 onpropertychange 最典型的生活实例:它有用,但绝不是“万能监听器”,你得判断 propertyName,得防止重复触发,得封装兼容逻辑,比如一个比较常见的兼容写法是:

function onValueChange(el, callback) {
  if ('oninput' in el) {
    el.addEventListener('input', callback);
  } else {
    el.attachEvent('onpropertychange', function (e) {
      if (e.propertyName === 'value') {
        callback();
      }
    });
  }
}

这段代码不复杂,但它背后是一个很现实的态度:别跟运行环境较劲,新项目当然用现代方案,input、change、MutationObserver,甚至框架自带的响应式系统,都比 onpropertychange 语义清楚、维护方便,但维护老项目时,你不能上来就一句“这什么垃圾代码”,然后把人家系统干崩,旧代码不是凭空长出来的,它往往是当年的人在有限条件下做出的最优解。

我个人对 onpropertychange 的看法挺复杂,我不建议今天任何新项目主动用它,它不是标准事件,现代浏览器也不认,写进去就是给自己埋兼容性坑,我又觉得它值得被认真理解,因为它像一个活标本,记录了前端“实时监听”这件事是怎么一步步演进的:从IE专有的属性变化事件,到 input 事件标准化,再到 MutationObserver 观察DOM变化,最后到框架层面的状态驱动,你理解了这条线,就不会再把“监听输入”和“监听属性”混为一谈。

说句掏心窝子的话,技术圈很容易对旧东西有一种居高临下的嘲笑:这都什么年代了还用IE?还用 attachEvent?还用 onpropertychange?但真到了具体生活里,很多单位的内网系统、老设备、老插件,就是被时间冻住了,你可以在博客里骂它,但你不能在用户面前把它删了,真正专业的态度是:先判断环境,再封装兼容,写好注释,记录技术债,能升级就推动升级,不能升级就把边界守好,别为了显得自己“现代”,把别人的业务搞成事故现场。

如果你今天问我:新项目要不要用 onpropertychange?我会很干脆地说:不用,除非你被困在IE的时光机里,但如果你正在维护一个老系统,看到它,别急着删,先看看它监听的是 value 还是别的属性,看看有没有重复触发,看看能不能用更清晰的兼容层包起来,它不是洪水猛兽,它只是一个属于过去的工具,工具会过时,但理解工具为什么存在,这件事永远不过时。

目录[+]