Blazor中无需JS代码实现同排子容器拖拽交换方法
在Blazor中无需JS实现同排子容器拖拽交换
实现思路
利用Blazor原生HTML拖拽事件(无需自定义JS),通过父组件维护子项列表,在拖拽事件触发时交换子项位置,配合CSS实现拖拽视觉反馈。
步骤1:定义拖拽项模型
创建类存储拖拽项的唯一标识和显示内容:
public class DraggableItem { public Guid Id { get; set; } = Guid.NewGuid(); public string Content { get; set; } = string.Empty; }
步骤2:编写父容器组件
父组件负责管理子项列表、处理核心拖拽逻辑:
<div class="drag-container"> @foreach (var item in Items) { <DraggableItemComponent Item="item" DraggedItemId="DraggedItemId" OnDragStart="() => StartDrag(item.Id)" OnDragOver="() => DragOver(item.Id)" OnDrop="() => Drop(item.Id)" /> } </div> @code { // 初始化示例子项 private List<DraggableItem> Items { get; set; } = new() { new DraggableItem { Content = "容器1" }, new DraggableItem { Content = "容器2" }, new DraggableItem { Content = "容器3" }, new DraggableItem { Content = "容器4" } }; // 记录当前拖拽项的ID private Guid? DraggedItemId { get; set; } // 拖拽开始:标记当前拖拽项 private void StartDrag(Guid itemId) { DraggedItemId = itemId; } // 拖拽经过:交换拖拽项与目标项的位置 private void DragOver(Guid targetItemId) { if (DraggedItemId == null || DraggedItemId == targetItemId) return; var draggedIndex = Items.FindIndex(i => i.Id == DraggedItemId); var targetIndex = Items.FindIndex(i => i.Id == targetItemId); if (draggedIndex == -1 || targetIndex == -1) return; // 交换列表中两项的位置 (Items[draggedIndex], Items[targetIndex]) = (Items[targetIndex], Items[draggedIndex]); // 更新拖拽项ID,保证连续拖拽时索引正确 DraggedItemId = targetItemId; } // 拖拽结束:清空拖拽标记 private void Drop(Guid targetItemId) { DraggedItemId = null; } }
步骤3:编写子项组件
子组件负责绑定拖拽事件、接收父组件回调,并提供视觉状态反馈:
<div class="draggable-item @GetItemClass()" draggable="true" @ondragstart="HandleDragStart" @ondragover="HandleDragOver" @ondrop="HandleDrop"> @Item.Content </div> @code { [Parameter, Required] public DraggableItem Item { get; set; } = null!; [Parameter] public Guid? DraggedItemId { get; set; } [Parameter] public Action? OnDragStart { get; set; } [Parameter] public Action? OnDragOver { get; set; } [Parameter] public Action? OnDrop { get; set; } // 根据拖拽状态生成样式类 private string GetItemClass() { var classList = new List<string>(); if (DraggedItemId == Item.Id) { classList.Add("dragging"); } return string.Join(" ", classList); } private void HandleDragStart(DragEventArgs e) { e.Data.EffectAllowed = "move"; OnDragStart?.Invoke(); } private void HandleDragOver(DragEventArgs e) { e.PreventDefault(); // 必须阻止默认行为才能触发Drop事件 OnDragOver?.Invoke(); } private void HandleDrop(DragEventArgs e) { e.PreventDefault(); OnDrop?.Invoke(); } }
步骤4:添加CSS样式
让子项同排显示,并添加拖拽时的视觉效果:
.drag-container { display: flex; gap: 1rem; padding: 1.5rem; flex-wrap: wrap; } .draggable-item { padding: 2rem 1.5rem; border: 2px solid #e0e0e0; border-radius: 8px; cursor: grab; background-color: #fff; transition: all 0.2s ease; min-width: 120px; text-align: center; } .draggable-item:active { cursor: grabbing; } .draggable-item.dragging { opacity: 0.5; transform: scale(0.98); }
效果说明
- 拖拽子容器时,该容器会呈现半透明、轻微缩小的视觉反馈
- 拖拽经过其他子容器时,两者会立即交换位置
- 整个过程完全基于Blazor的C#逻辑和原生HTML事件,未引入任何JavaScript代码
内容的提问来源于stack exchange,提问作者Cannie
相关产品推荐
相关产品推荐

