jstree拖拽DND图标DOM已变更但界面不渲染问题求助
我之前处理过不少jstree拖拽相关的问题,你遇到的这种DOM类已经更新但拖拽图标渲染不生效的情况,大概率是版本兼容性或者没有利用jstree原生API导致的。结合你描述的场景——拖拽到指定dropzone div时图标始终显示禁止符号(jstree-er),DOM修改后界面无变化,还有切换jQuery版本后问题消失的线索,给你几个针对性的解决方案:
核心原因分析
直接手动修改#jstree-dnd i的类名,虽然能更新DOM,但jstree内部的拖拽状态并没有同步,尤其是在新版本jQuery中,事件触发顺序、元素引用逻辑和jstree的预期不匹配,导致组件没有触发重绘。另外你提到data.helper.find('.jstree-icon')返回空,也是因为不同jQuery版本下,jstree创建的拖拽辅助元素结构有变化。
最优解决方案:利用jstree原生属性控制状态
jstree的dnd_move.vakata事件提供了原生的data.is_valid属性,用来标记当前目标是否可放置,设置这个属性后,jstree会自动处理拖拽图标的状态,完全不需要手动修改DOM:
$(document).on('dnd_move.vakata', function (e, data) { var t = $(data.event.target); // 直接通过原生属性标记是否为合法拖拽目标 data.is_valid = t.hasClass("dropzone"); });
这种方式完全遵循jstree的内部逻辑,不会出现DOM和组件状态不同步的问题,也能适配不同的jQuery版本(只要版本组合符合jstree官方要求)。
备选方案:手动修改DOM并强制重绘
如果因为某些原因必须手动操作DOM,那在修改类名后需要强制触发元素重绘,解决界面不更新的问题:
$(document).on('dnd_move.vakata', function (e, data) { var t = $(data.event.target); var $dragIcon = $("#jstree-dnd i"); if (t.hasClass("dropzone")) { $dragIcon.removeClass('jstree-er').addClass('jstree-ok'); } else { $dragIcon.removeClass('jstree-ok').addClass('jstree-er'); } // 强制触发重绘,解决DOM更新但界面不渲染的问题 $dragIcon.hide().show(0); });
版本兼容性检查
你提到切换旧版本jQuery后问题消失,说明当前使用的jQuery和jstree版本不兼容。建议去jstree官方文档确认推荐的jQuery版本范围,比如部分旧版jstree只兼容jQuery 1.x或2.x版本,新版本jQuery 3.x可能会出现这类诡异的渲染问题。
内容的提问来源于stack exchange,提问作者Janine Rawnsley

