jQuery 3.6搭配Tabulator 5.2.7时函数绑定调用失效如何解决?
问题环境
- jQuery 3.6.0
- Tabulator 5.2.7
- 页面同时引入了jQuery UI与Tabulator官方jQuery wrapper
页面头部引入代码如下:
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="./jquery-ui.min.css"> <link rel="stylesheet" href="./tabulator.min.css"> <script src = "./jquery-3.6.0.min.js"></script> <script src="./jquery-ui.min.js"></script> <script type="text/javascript" src="./tabulator.min.js"></script> <script type="text/javascript" src="./jquery_wrapper.js"></script> </head>
问题表现
通过AJAX加载XML解析后初始化Tabulator表格,初始渲染正常,触发切换数据逻辑时调用replaceData/setData方法抛出如下错误:
jquery-3.6.0.min.js:2 Uncaught Error: no such method 'replaceData' for tabulator widget instance at Function.error (jquery-3.6.0.min.js:2:2616) at HTMLDivElement.<anonymous> (jquery-ui.min.js:6:2067) at Function.each (jquery-3.6.0.min.js:2:3003) at S.fn.init.each (jquery-3.6.0.min.js:2:1481) at V.fn.<computed> [as tabulator] (jquery-ui.min.js:6:1951) at HTMLInputElement.<anonymous> (index.html:99:48) at HTMLInputElement.dispatch (jquery-3.6.0.min.js:2:43064) at v.handle (jquery-3.6.0.min.js:2:41048)
调试jquery_wrapper.js时,发现遍历Tabulator.prototype映射jQuery方法的逻辑中,仅能获取到bindModules一个函数(重复出现两次)。
核心业务代码如下:
$(document).ready(function() { $.ajax({ type: "GET", url: xmlFileName, dataType: "xml", success: function(xml) { // 解析xml生成Tabulator所需数据 // ... $('#my-table').tabulator({ data: /* 解析完成的初始数据 */, dataTree: true, columns: [ {title: 'Name', field: 'name', headerSort:false}, // 其余列配置 ] }); $('数据切换触发元素').change(function() { $('#my-table').tabulator("replaceData", /* 新数据集 */); }); } }); });
问题根因
该问题既不是版本兼容问题,也不是方法调用语法错误,本质是jQuery插件命名空间冲突:
- jQuery UI内置的widget工厂会自动在jQuery原型上注册
$.fn.tabulator方法,这个方法是jQuery UI的widget实例方法,本身没有映射Tabulator的replaceData、setData等表格实例方法。 - 由于脚本加载顺序问题,Tabulator自带的jquery_wrapper没有成功覆盖jQuery UI注册的同名方法,所有通过
$(选择器).tabulator()发起的调用实际都被jQuery UI的widget逻辑接管。 - 初始渲染能成功是因为传入配置对象的调用形式刚好匹配jQuery UI widget的初始化传参规则,后续传入字符串方法名调用时,jQuery UI找不到对应的widget方法就会抛出
no such method错误。调试时看到原型遍历仅能获取到bindModules,就是因为此时拿到的是jQuery UI创建的widget实例原型,而非Tabulator本身的原型对象。
解决方案
根据项目是否需要保留jQuery UI依赖,二选一即可:
方案1:移除冗余依赖(推荐)
Tabulator 5.x的运行不依赖jQuery UI,如果项目没有其他功能用到jQuery UI,直接删除页面中jquery-ui.min.css和jquery-ui.min.js的引入即可,冲突消除后原有jQuery风格的方法调用可以正常运行。
方案2:保留jQuery UI时的适配
如果项目其他功能依赖jQuery UI无法移除,做两处调整即可彻底解决问题:
- 调整脚本加载顺序,确保Tabulator的jquery_wrapper在jQuery UI之后加载,让wrapper注册的
$.fn.tabulator覆盖jQuery UI的同名方法:
<head> <link rel="stylesheet" href="./jquery-ui.min.css"> <link rel="stylesheet" href="./tabulator.min.css"> <script src="./jquery-3.6.0.min.js"></script> <!-- 先加载jQuery UI --> <script src="./jquery-ui.min.js"></script> <script type="text/javascript" src="./tabulator.min.js"></script> <!-- 最后加载Tabulator jQuery wrapper,确保覆盖同名方法 --> <script type="text/javascript" src="./jquery_wrapper.js"></script> </head>
- (最稳妥,彻底规避命名冲突)初始化时直接保存Tabulator实例,后续操作全部调用实例方法,不经过jQuery插件层:
$(document).ready(function() { $.ajax({ type: "GET", url: xmlFileName, dataType: "xml", success: function(xml) { // 解析xml生成表格数据 // ... // 初始化时保存表格实例 const tableInstance = new Tabulator("#my-table", { data: /* 解析好的初始数据 */, dataTree: true, columns: [ {title: 'Name', field: 'name', headerSort:false}, // 其余列配置 ] }); $('数据切换触发元素').change(function() { // 直接调用实例方法,不受jQuery插件冲突影响 tableInstance.replaceData(/* 新数据集 */); }); } }); });
内容的提问来源于stack exchange,提问作者Gordon Ludlow
相关产品推荐
相关产品推荐

