实用的 Vue.Draggable 拖拽插件

实用的 Vue.Draggable 拖拽插件Vue.Draggable 是一款基于 Sortable.js 实现的 vue 拖拽插件。支持移动设备拖拽,可以在不同列表间拖拽,支持 vue 2 过渡动画兼容,总之是一款非常优秀的 vue 拖拽组件

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

Vue.Draggable 是一款基于 Sortable.js 实现的 vue 拖拽插件。支持移动设备拖拽,可以在不同列表间拖拽,支持 vue 2 过渡动画兼容,总之是一款非常优秀的 vue 拖拽组件。

Vue.Draggable 拖拽组件的特点是:换位置时,相当于是从当前位置移除,插入到另一个地方,插入地方的数据都往后移动一位。

Github 地址: github.com/SortableJS/…

中文文档:www.itxst.com/vue-draggab…

安装

npm i -S vuedraggable

使用

// 引入
import draggable from "vuedraggable";

// 组件注册
export default {
  components: {
    draggable,
  },
};

// 使用
<draggable></draggable>;

实战

ic_drag_1.png

模拟数据

export const mockData = {
  fruitColumns: {
    columns: [
      { name: "苹果", key: "apple", checked: true },
      { name: "梨子", key: "pear", checked: true },
      { name: "桃子", key: "peach", checked: false },
      { name: "西瓜", key: "watermelon", checked: true },
      { name: "榴莲", key: "durian", checked: false },
      { name: "百香果", key: "passion fruit", checked: true },
      { name: "哈密瓜", key: "Cantaloupe", checked: true },
      { name: "香蕉", key: "banana", checked: true },
      { name: "菠萝", key: "Pineapple", checked: true },
    ],
  },
  foodColumns: {
    columns: [
      { name: "粥", key: "pineapple", checked: true },
      { name: "米饭", key: "rice", checked: true },
      { name: "饺子", key: "dumpling", checked: true },
      { name: "面条", key: "noodle", checked: false },
      { name: "豆浆", key: "soy milk", checked: true },
      { name: "面包", key: "bread", checked: false },
    ],
  },
};

模块展示

数据源是一个列表,同时展示的是多个拖拽组件。

  1. 通过group来区分组,可以在相同的组之间互相拖拽。本次实践的是不同组的拖拽组件,不能互相拖拽。
  2. :draggable=".card" 定义了哪些元素是可以被拖动的
<template>
  <div class="m-list">
    <div class="m-list-item" v-for="(item, index) in dragList" :key="item.type" :id="item.type" >
      <template v-if="item && item.data && item.data.length">
        <div class="m-list-item-header">
          <div class="title">{{ item.title }}</div>
        </div>
        <draggable v-model="item.data" class="m-list-item-content" ghostClass="card-ghost" chosenClass="card-chosen" dragClass="card-drag" draggable=".card" :group="item.type" animation="300" >
          <transition-group>
            <div v-for="data in item.data" :key="data.key" :class="[ 'card', { 'card-active': item.checkedKeys.includes(data.key), }, ]" @click.stop.prevent="handleDragClick(data, item, index)" >
              {{ data.name }}
            </div>
          </transition-group>
        </draggable>
      </template>
    </div>
  </div>
</template>

数据处理

  1. 将模拟数据转为拖拽组件需要的数据:queryColumns()
  2. 点击事件,进行选中和未选中切换,对应的状态也会更改,默认是白色,选中时淡蓝色:handleDragClick()
<script> import * as R from "ramda"; import draggable from "vuedraggable"; // 拖拽列表 const dragList = [ { type: "fruit", key: "fruitColumns", title: "水果", data: [] }, { type: "food", key: "foodColumns", title: "食物", data: [] }, ]; export default { data() { return { dragList, }; }, components: { draggable, }, mounted() { this.queryColumns(); }, methods: { queryColumns() { this.dragList = R.pipe( R.toPairs, R.map(([key, props]) => { let result = R.mergeDeepRight( R.find(R.propEq("key", key))(this.dragList), { key, ...props, } ); // 对应填充 result.data = R.pathOr([], ["columns"], result); result.checkedKeys = R.map( (o) => o.key, R.filter((r) => r.checked, R.pathOr([], ["data"], result)) ); return result; }) )(mockData); }, handleDragClick(data, item, index) { if (!R.includes(data.key, item.checkedKeys)) { item.checkedKeys = R.append(data.key, item.checkedKeys); } else { item.checkedKeys = R.filter((o) => o !== data.key, item.checkedKeys); } // 此处要注意一下,更改的方式 R.adjust(index, () => changeCheckStatus(item), this.dragList); }, }, }; </script>

拖拽样式处理

  1. ghostClass="card-ghost":设置拖动元素的占位符样式,需要加!important 才能生效(粉色背景,放大)
  2. chosenClass="card-chosen":被选中目标的样式,需要加!important 才能生效(淡蓝色背景)
  3. dragClass="card-drag":拖动元素的样式,需要加!important 才能生效(蓝色背景)
<style lang="scss" scoped> .m-list { width: 500px; &-item { margin-bottom: 32px; cursor: move; &:last-of-type { margin-bottom: 16px; } &-header { display: flex; margin-bottom: 20px; align-items: center; justify-content: space-between; line-height: 20px; .title { font-size: 16px; font-weight: bold; } } &-content { display: flex; flex-wrap: wrap; > span { flex: 1; display: flex; flex-wrap: wrap; } /* 被拖拽对象的样式 */ .card { display: flex; align-items: center; justify-content: center; width: 156px; height: 40px; border: 1px solid #ccc; border-radius: 4px; margin-right: 8px; margin-bottom: 8px; // 动画实现 transition: transform 0.3s; &-active { color: #1890ff; border-color: #a8d2ee; background-color: #e6f7ff; cursor: move; } /* 被选中样式:必须在ghost样式之前 */ &-chosen { color: #fff; } /* 拖动元素样式 */ &-drag { background-color: #1890ff !important; color: #fff; border: none; } /* 拖动元素占位符样式 */ &-ghost { background-color: pink !important; color: #fff; transform: scale(1.08); } } .card + .card { margin-bottom: 8px; } } } } </style>

视频查看

ic_drag_4.png

今天的文章实用的 Vue.Draggable 拖拽插件分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21036.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注