You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue Draggable在Bootstrap Vue的b-table中失效,求排查原因

Vue2 + Bootstrap Vue 表格行拖拽失效的修复方案

你遇到的问题核心是拖拽组件与Bootstrap Table的DOM结构冲突,加上一处语法错误导致拖拽功能无法正常工作,以下是具体修复步骤:

问题分析

  1. DOM结构嵌套冲突:原代码用<draggable>包裹了整个<b-table>,但<b-table>会自动生成自身的<tbody>,最终DOM结构变成<tbody><b-table><tbody>...</tbody></b-table></tbody>,拖拽组件无法识别正确的可拖拽行元素。
  2. Handle选择器语法错误::handle=".handle"写法错误,应该传入字符串形式的CSS选择器".handle",否则会被解析为Vue实例属性而非选择器。

修复后的完整代码

模板部分

<b-overlay :show="loading" rounded="sm" spinner-variant="primary">
  <b-table 
    :fields="fields" 
    :items="accounts" 
    responsive 
    head-variant="light"
  >
    <!-- 自定义tbody,替换为draggable组件 -->
    <template #tbody="props">
      <draggable
        v-model="accounts"
        @end="onDragEnd"
        tag="tbody"
        :move="onMove"
        :handle="'.handle'"
      >
        <tr v-for="item in props.items" :key="item.id" class="item">
          <td v-for="field in props.fields" :key="field.key">
            <!-- 渲染handle列 -->
            <template v-if="field.key === 'handle'">
              <div class="handle-container" style="cursor: move;">
                <i class="fa fa-align-justify fa-lg handle"></i>
              </div>
            </template>
            <!-- 渲染icon列 -->
            <template v-else-if="field.key === 'icon'">
              <b-card
                class="my-2"
                :style="{ 'background-color': item.color }"
              >
                <b-card-sub-title>
                  <span v-html="getIcon(item.icon)"></span>
                </b-card-sub-title>
              </b-card>
            </template>
            <!-- 渲染name列 -->
            <template v-else-if="field.key === 'name'">
              <b>{{ item.name }}</b>
            </template>
            <!-- 渲染balance列 -->
            <template v-else-if="field.key === 'balance'">
              <span><i class="fas fa-euro-sign"></i> {{ item.balance.toFixed(2) }}</span>
            </template>
            <!-- 渲染lastUpdate列 -->
            <template v-else-if="field.key === 'lastUpdate'">
              {{ item.lastUpdate }}
            </template>
            <!-- 渲染actions列 -->
            <template v-else-if="field.key === 'actions'">
              <span class="cursor-pointer" v-b-modal="`bank-account-${item.id}-edit-modal`">
                <i class="fas fa-edit fa-lg"></i>
              </span>

              <modal
                :id="`bank-account-${item.id}-edit-modal`"
                :title="$t('actions.edit-bank-account')"
                :ok-disabled="!canSubmit"
                @ok-pressed="$refs.form?.submit()"
              >
                <add-bank-account-form 
                  ref="form"
                  :can-submit="canSubmit"
                  :id="item.id"
                  @form-updated="updateFormValidity"
                  @item-added="payload => itemUpdated(payload, item.id)"
                />
              </modal>

              <span class="cursor-pointer trash-icon" @click="deleteItem(item.id)">
                <i class="fas fa-trash fa-lg"></i>
              </span>
            </template>
          </td>
        </tr>
      </draggable>
    </template>

    <!-- 表头handle列占位 -->
    <template #head(handle)="data">
      {{ '' }}
    </template>
  </b-table>
</b-overlay>

脚本部分(仅需修改一处)

无需大改,仅确保handle选择器正确传递即可,其余逻辑保持不变:

// ... 其余代码不变
<draggable
  v-model="accounts"
  @end="onDragEnd"
  tag="tbody"
  :move="onMove"
  :handle="'.handle'" // 这里修正为字符串选择器
>
// ... 其余代码不变

关键修复点说明

  1. 利用Bootstrap Table的tbody插槽:通过#tbody插槽替换默认的<tbody>,让<draggable>直接作为表格的tbody容器,避免DOM嵌套冲突。
  2. 修正Handle选择器:将:handle=".handle"改为:handle="'.handle'",确保拖拽组件能正确识别触发拖拽的元素。
  3. 显式渲染表格行:通过v-for遍历表格数据渲染<tr>,让拖拽组件能直接绑定到可拖拽的行元素上。

额外注意事项

  • 确保accounts数组中的每个元素都有唯一id,这是v-for的key必须项,也能让拖拽组件正确跟踪元素位置。
  • 给handle-container添加cursor: move样式,提升用户交互体验。

内容的提问来源于stack exchange,提问作者screw4445

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 23:35:02