赞
踩
项目开发中需要用到 拖拽组件,因为 前端技术框架 是 Vue2 ,
这里就使用了 Vue 的一款 拖拽插件 vue.draggable ,
一般基本的需求都能满足 ,这里使用了多个 draggable 嵌套,达到两级之间相互拖拽的功能。
以下是类似 teambition 的效果图片,最外层为一个 draggable ,可以左右拖动,
然后每个块里面还有小块,小块组成一个 draggable ,
可以上下拖动,也可以在大的块之间拖动。
这里说一下实现原理。
首先,要搞清楚 draggable 的 Api ,
Vue.Draggable 是一款基于 Sortable.js 实现的 Vue 拖拽插件。
支持 移动设备、拖拽 和 选择文本、智能滚动 ,
可以在 不同列表间 拖拽、不依赖 jQuery 为基础、Vue2 过渡动画兼容、支持撤销操作 ,
使用起来特别简单,对被拖拽元素也没有 CSS 样式的特殊要求。
中文文档 :
里面 基本属性 和 方法都有讲到 ,有时间的可以去学习一下,
要查看详细的说明可以去 git 看官方文档说明,
官方文档 :
GitHub - SortableJS/Vue.Draggable: Vue drag-and-drop component based on Sortable.js
这里用到了以下几个属性和事件,着重说明下:
1、group :拖拽分组 ,多组之间相互拖拽 ,可以实现不同数组之间相互拖拽
比如 group 都为 itxst 的组之间才可以相互拖动,
本文例子中分别给两个 draggable 设置了不同的 group 属性,是防止大的被拖到小的块里面去
示例 :group="viewer" 或 group : { name: "viewer", pull: "clone", put: false }
2、sort : 是否开启内部排序( true / false )
3、disable : 通过 disabled 属性实现 开启 或 禁用 vue.draggable 的 拖拽效果
4、animation :通过 animation 属性设置 vue.draggable 过渡效果
这样拖动时 过渡位置 就不会显的太生硬 。
5、handle : 设置(限制)可拖拽区域
6、ghostClass :目标位置占位符的样式及需要停靠位置的样式
7、chosenClass :被选中目标的样式
8、dragClass :拖动元素的样式
9、list :作为 值属性 的 替代 ,list 是一个与 拖放 同步 的 数组
( 比如说, :list = "data" , 就是说,拖拽组件里面的内容数据绑定了 这个 data 值,
一开始这个 data 可能为 [ ] 空数组,但后续通过绑定 @add="addCommand" ,
即可通过拖拽生成事件来将所拖拽内容本身的数据内容添加至 data 数组中去了,
也就是通过拖拽新生成的数据内容会实时更新至 data 里面了,因此 data 也就有了数据 。)
这里在 二级 draggable 使用了该属性 ,因为 两个 draggable 用到了同一数据源 ,
二级 draggable 中用 list 替代 v-model
10、move : 自定义控制那些元素可以拖拽或不允许拖拽并控制是否允许停靠
11、start() : 开始拖动时触发的事件
12、add() :从一个数组拖拽到另外一个数组时触发的事件
11、end() :拖拽完成时的事件
如果想和后端实现动态更新,可以在这个方法里面和后端进行数据交互
tag : 自定义 导航编译生成后的 HTML 标签
然后就是示例 demo 了,这里一些代码段,样式什么的大家可以自由发挥
1、第一步 ,安装 vue.draggable 插件,yarn 或者 npm 都可以
yarn add vuedraggable
npm i -S vuedraggable"vuedraggable": "^2.43.3"
2、第二步 ,使用插件
import draggable from 'vuedraggable'3、注册组件
components: { draggable }
- <script>
- import draggable from "vuedraggable";
-
- export default {
- components: { draggable },
- data() {
- return {
- disabled: false,
- // 定义要被拖拽对象的数组
- arr1: [
- { id: 1, name: "www.itxst.com(不允许停靠)" },
- { id: 2, name: "www.jd.com" },
- { id: 3, name: "www.baidu.com" },
- { id: 5, name: "www.google.com" },
- { id: 4, name: "www.taobao.com(不允许拖拽)" },
- ],
- };
- },
- methods: {
- // move回调方法
- moveCommand(e) {
- // 目标是容器不允许停靠
- if (
- e.relatedContext.element &&
- e.relatedContext.element.type === "container"
- )
- return false;
- // 布局容器不允许容器拖拽
- if (
- e.relatedContext.element &&
- e.draggedContext.element.type === "container"
- )
- return false;
- return true;
- },
- // 开始拖动时触发的事件
- startCommand(e) {
- console.log("移动中...", e);
- },
- // 从一个数组拖拽到另外一个数组时触发的事件
- addCommand(e) {},
- // 拖拽完成时的事件
- endCommand(e) {
- console.log("结束移动...", e);
- },
- },
- };
- </script>
- <div>
- <draggable class="list-group" group="task" v-model="projectList" @end="draggerEnd()">
- <div class="card-list-span" v-for="(process, index) in projectList" :key="process.opListId">
- <div class="span-header">
- <div class="header-title">
- {{ process.opListName }}
- </div>
- </div>
- <div class="span-body">
- <div class="body-list">
- <draggable
- group="project"
- :list="process.taskVoList"
- @end="taskDraggerEnd()"
- >
- <div
- class="body-list-span"
- v-for="task in process.taskVoList"
- :key="task.opTaskId"
- >
- <div>
- {{ task.opTaskTitle }}
- </div>
- <div>{{ task.opTaskHandler }}</div>
- </div>
- </draggable>
- <div slot="footer">
- <Author author="yunygl-yylcgl-cjrw">
- <div class="add-task" @click="addTask(index)">
- <i class="el-icon-plus" style="margin-right: 5px;"></i>
- 添加任务
- </div>
- </Author>
- </div>
- </div>
- </div>
- </div>
- </draggable>
- </div>
-
- data() {
- return {
- projectList: [
- {
- id: "001",
- name: "流程一",
- taskList: [
- {id: "001001",taskTitle: "任务一"},
- {id: "001002",taskTitle: "任务二"}
- ]
- },
- {
- id: "002",
- name: "流程二",
- taskList: [
- {id: "002001",taskTitle: "任务一"}
- ]
- }
- ]
- }
-
- method: {
- // 添加任务
- addTask(index) {
- this.projectList[index].taskList.push( {id: "00200232",taskTitle: "任务二"})
- },
- }
项目使用 :
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。