在2024年3月,jQuery的最新版本是3.7。在检查代码时,发现有超过2000处引用了旧版本的jQuery 1.8.3。为了更新这些引用,花费了一整天的时间将它们指向最新的jQuery版本,并添加了对jQuery Migrate插件的引用,该插件可以帮助处理已弃用代码。然而,当完成这些工作后,登录按钮变得无响应,并出现了错误信息:“在初始化之前无法调用对话框的方法——尝试调用方法close”。
错误堆栈指向了以下代码行,这是jQuery UI对话框关闭按钮的事件处理程序:
<script>
.click(function() {
$(this).dialog('close');
location.reload();
})
</script>
意识到,在jQuery 3中,上述代码中的$(this)
不再引用当前活动的jQuery UI对话框。因此,$(this).dialog()
是未定义的,错误消息提示在调用方法close之前先初始化对话框。为了修复这个问题,添加了.closest('.ui-dialog-content')
来定位最近的jQuery UI对话框:
<script>
.click(function() {
$(this).closest('.ui-dialog-content').dialog('close');
location.reload();
})
</script>
这样,登录页面就可以正常工作了,但是在后续页面上的一个按钮出现了类似的错误信息:“在初始化之前无法调用对话框的方法——尝试调用方法enable”:
<script>
$('#remove-button').toolbarbutton('enable', function() {
...
});
</script>
在这里,toolbarbutton
是代码中使用的一个自定义UI控件。经过一些调试,确定在调用方法enable之前,$('#remove-button')
没有被初始化为toolbarbutton()
,尽管初始化代码在$(document).ready()
方法中已经存在。通过在调用enable之前再次初始化按钮来解决了这个问题:
<script>
$('#remove-button').toolbarbutton({
state: 'enabled'
});
$('#remove-button').toolbarbutton('enable', function() {
...
});
</script>
然后是这个顽固的jQuery spinner控件,它在调用spinner-up方法时抱怨未初始化,尽管已经使用了上述技巧。暂时通过捕获异常来修复它。由于该方法只是在某些情况下禁用spinner,这是可选的,因此对UI没有影响:
<script>
try {
$(this.element).next().next('.spinner-up').setElementDisabled(false);
} catch (err) {
console.log("spinner error: " + err);
}
</script>
很少在JavaScript中使用try/catch,但在这种情况下,捕获异常并忽略错误是唯一能让事情工作的方法。
在修复了数百个类似的问题之后,页面部分功能正常,但复选框仍然存在问题。然后不得不将已弃用的.attr()
替换为.prop()
,这样复选框才能再次工作:
<script>
// element.attr('checked', false); // 旧版本
element.prop('checked', false);
// 新版本
</script>
还更新了对.live()
的几次调用(这已被移除)到.on()
(jQuery v3支持),以便事件绑定能够正常工作。接下来,遇到了一个JavaScript错误:$.browser.msie
,这是一个布尔值,用于确定用户是否在Microsoft Internet Explorer中。由于IE不再被支持,这个属性在最新版本的jQuery中已被移除。通过声明一个自定义方法来解决这个问题,该方法为$.browser.msie
返回false
:
<script>
(function($) {
// 定义一个空对象$.browser
$.browser = {};
// 用一个虚拟的msie属性扩展jQuery.browser
$.extend($.browser, {
msie: false
});
// 覆盖对$.browser.msie的访问
Object.defineProperty($.browser, 'msie', {
get: function() {
return false;
}
});
})(jQuery);
</script>
这样,解析用户代理的代码现在可以正常工作了。最后一个挑战也是最困难的一个,是偶尔出现的空的OK/Cancel按钮,如下所示:
这两个按钮应该是OK和Cancel,虽然它们是空的,但仍然按设计工作。根据,如果页面加载了多个冲突的jQuery版本,例如同时加载了1.8和3版本的.js文件,就会出现这个问题。经过大量的故障排除努力,发现尽管已经将代码中的所有jQuery引用更新到了最新版本,但这个门户的这部分是从远程站点加载应用程序的,该站点仍然包含过时的jQuery库。由于无法更新远程jQuery库,不得不使用CSS为Cancel按钮添加❌,为OK按钮添加✓,以便按钮看起来不为空:
<style>
button.okbutton::before {
content: "\2713";
}
button.cancelbutton::before {
content: "\274C";
}
</style>