升级jQuery 1.11至3.x时出现Uncaught TypeError循环结构转JSON错误
解决jQuery 3.x升级后JSON.stringify循环结构错误
问题原因
控制台报错Uncaught TypeError: Converting circular structure to JSON,是因为Nestable插件的serialize方法中,直接通过$.extend({}, li.data())提取了元素的所有数据。在jQuery 3.x中,元素的data()会包含插件绑定的实例对象(比如代码里的nestable插件实例),这个实例又反向关联了DOM元素,形成循环引用,导致JSON无法序列化。
修复方案
修改serialize方法中提取元素数据的逻辑,只保留需要的自定义数据,或者排除插件自动添加的循环引用属性。
方案1:明确指定需要序列化的字段(推荐)
如果自定义数据是特定字段(比如id、title等),直接提取这些字段,避免混入插件内部数据:
serialize: function() { var data, depth = 0, list = this; step = function(level, depth) { var array = [ ], items = level.children(list.options.itemNodeName); items.each(function() { var li = $(this), // 只提取你需要的自定义数据字段 item = { id: li.data('id'), title: li.data('title') // 添加你实际用到的其他字段 }, sub = li.children(list.options.listNodeName); if (sub.length) { item.children = step(sub, depth + 1); } array.push(item); }); return array; }; data = step(list.el.find(list.options.listNodeName).first(), depth); return data; }
方案2:过滤插件自动添加的属性
如果需要保留所有自定义数据,只排除插件添加的nestable和nestable-id属性:
serialize: function() { var data, depth = 0, list = this; step = function(level, depth) { var array = [ ], items = level.children(list.options.itemNodeName); items.each(function() { var li = $(this), rawData = li.data(), // 过滤掉插件自动添加的循环引用属性 item = Object.fromEntries( Object.entries(rawData).filter(([key]) => !['nestable', 'nestable-id'].includes(key)) ), sub = li.children(list.options.listNodeName); if (sub.length) { item.children = step(sub, depth + 1); } array.push(item); }); return array; }; data = step(list.el.find(list.options.listNodeName).first(), depth); return data; }
为什么jQuery 1.11没有这个问题?
在旧版本jQuery中,插件实例可能没有被存入元素的data集合,或者data()方法的返回结构不包含这类循环引用的对象,因此序列化时不会触发错误。升级到3.x后,jQuery对data的存储机制有调整,导致插件实例被包含在返回结果中,进而引发循环引用。
内容的提问来源于stack exchange,提问作者Shawn Purdy
相关产品推荐
相关产品推荐

