jQuery UI Sortable多连接拖拽时如何根据方向设置state变量
问题描述
使用jQuery UI的Sortable实现两个列表的拖拽排序,需求如下:
- 将
#sortable2中的<li>拖拽至#sortable1时,变量state赋值为0 - 将
#sortable1中的<li>拖拽至#sortable2时,变量state赋值为1
原实现代码如下:
原JavaScript代码
$(function() { $("#sortable1, #sortable2").sortable({ connectWith: ".connectedSortable" }).disableSelection(); $("#sortable2").sortable({ update: function(event, ui) { $(this).children().each(function(index) { if ($(this).attr('data-position') != (index + 1)) { $(this).attr('data-position', (index + 1)).addClass('updated'); } }) saveNewPositions(); } }).disableSelection(); }); function saveNewPositions() { var positions = []; $('.updated').each(function() { positions.push([$(this).attr('data-index'), $(this).attr('data-position'), $(this).attr('data-type')]); $(this).removeClass('updated'); }) $.ajax({ url: SITE_URL + 'standart/islem.php?page=sortable', method: 'POST', dataType: 'text', data: { positions: positions, pageID: 1, }, success: function(data) { data = data.split(":::", 2); var message = data[0], answer = data[1]; } }) }
原HTML代码
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/jquery-3.6.0.js"></script> <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script> <ul id="sortable1" class="connectedSortable"> <li data-index="1" data-position="1">first row</li> <li data-index="2" data-position="2">second row</li> </ul> <ul id="sortable2" class="connectedSortable"> <li data-index="1" data-position="1">2. first row</li> <li data-index="2" data-position="2">2. second row</li> </ul>
解决方案
要实现跨列表拖拽时的state赋值,核心是利用jQuery UI Sortable的**receive事件**——该事件会在元素从另一个关联的Sortable容器被拖拽进来时触发。结合ui.sender可以获取元素的原父容器,从而判断拖拽方向。
另外需要注意:原代码中重复初始化了#sortable2的Sortable,这会导致事件绑定冲突,需要合并为一次初始化,并为两个容器统一绑定必要的事件。
修改后的完整代码
JavaScript代码
$(function() { // 初始化两个Sortable容器,统一配置事件 $("#sortable1, #sortable2").sortable({ connectWith: ".connectedSortable", // 元素从外部拖拽进来时触发 receive: function(event, ui) { let state; // 判断原容器和目标容器 if (ui.sender.attr('id') === 'sortable2' && $(this).attr('id') === 'sortable1') { state = 0; // 从sortable2到sortable1 } else if (ui.sender.attr('id') === 'sortable1' && $(this).attr('id') === 'sortable2') { state = 1; // 从sortable1到sortable2 } // 这里可以根据state做后续处理,比如传入saveNewPositions console.log('当前state值:', state); }, // 排序完成后更新位置信息 update: function(event, ui) { $(this).children().each(function(index) { if ($(this).attr('data-position') != (index + 1)) { $(this).attr('data-position', (index + 1)).addClass('updated'); } }); saveNewPositions(); } }).disableSelection(); }); function saveNewPositions() { var positions = []; $('.updated').each(function() { positions.push([$(this).attr('data-index'), $(this).attr('data-position'), $(this).attr('data-type')]); $(this).removeClass('updated'); }); $.ajax({ url: SITE_URL + 'standart/islem.php?page=sortable', method: 'POST', dataType: 'text', data: { positions: positions, pageID: 1, // 如果需要把state传给后端,可以在这里添加 // state: state }, success: function(data) { data = data.split(":::", 2); var message = data[0], answer = data[1]; } }); }
HTML代码(无需修改)
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/jquery-3.6.0.js"></script> <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script> <ul id="sortable1" class="connectedSortable"> <li data-index="1" data-position="1">first row</li> <li data-index="2" data-position="2">second row</li> </ul> <ul id="sortable2" class="connectedSortable"> <li data-index="1" data-position="1">2. first row</li> <li data-index="2" data-position="2">2. second row</li> </ul>
关键说明
receive事件的作用:当元素从其他Sortable容器拖拽进来时触发,ui.sender指向元素的原父容器,通过对比原容器和当前容器的ID,即可确定拖拽方向并赋值state。- 合并Sortable初始化:避免重复初始化导致的事件冲突,同时为两个容器统一绑定
update事件,确保两个列表的位置更新都能被处理。 state的后续使用:如果需要将state传递给后端,可以在saveNewPositions函数中添加对应的参数,或者在receive事件中把state存储为全局变量/元素属性,再在AJAX请求中携带。
内容的提问来源于stack exchange,提问作者user18589150
相关产品推荐
相关产品推荐

