vue 拖拽排序组件——Vue.Draggable / 自定义指定的随机拖拽
参考文档:
已封装的vue第三方扩展组件git:https://github.com/SortableJS/Vue.Draggable
介绍
vuedraggable
安装 (安装两个依赖)
通过npm安装
C/C++ Code复制内容到剪贴板
- npm install vuedraggable sortable --save
插件应用
用draggable包裹被拖拽的元素,options是拖拽效果行为的相关配置,和sortable的配置基本完全一样,start end move是相关事件。
XML/HTML Code复制内容到剪贴板
- <template>
- <draggable v-model="selectedLessonList" :options="{group:'people'}" @start="dropStart" @end="dropEnd" :move="checkMove">
- <ul v-for="item in selectedLessonList">
- <li>
- <i class="control-icon up-icon"></i><span>{{item.label}}</span>
- </li>
- </ul>
- </draggable>
- </template>
- <script>
- import draggable from 'vuedraggable'
- export default {
- name: 'teachPlanForm',
- data() {
- return {
- selectedLessonList: [], //已选择的课程数组
- }
- },
- components: {
- draggable
- },
- mounted() { // 这个是页面创建的时候,就执行相关的方法
- this.init()
- },
- methods: {
- dropStart() {
- console.log("开始拖动");
- },
- dropEnd(evt) {
- // 拖动结束
- console.log('拖动前的索引 :' + evt.oldIndex);
- console.log('拖动后的索引 :' + evt.newIndex);
- console.log(this.selectedLessonList);//已被改变后的数组
- },
- checkMove() {
- console.log("检测移动时状态");
- },
- }
- }
- </script>
自定义指令的随机拖拽:
XML/HTML Code复制内容到剪贴板
- <!-- 自定义指令v-drag -->
- <div class="study_icon" v-drag="greet"></div>
JavaScript Code复制内容到剪贴板
- <script>
- export default {
- methods: {
- greet(val) { // 接受传来的坐标
- console.log(val)
- }
- },
- directives: { //自定义拖拽功能
- drag: {
- bind: function(el, binding) {
- let oDiv = el; //当前元素
- oDiv.addEventListener('touchstart', function(e) {
- let footerH = document.getElementsByTagName('footer')[0].clientHeight;
- let touches = e.touches[0];
- //鼠标按下,计算当前元素距离可视区的距离
- let disX = touches.clientX - oDiv.offsetLeft;
- let disY = touches.clientY - oDiv.offsetTop;
- oDiv.addEventListener('touchmove', function(e) {
- let touches = e.touches[0];
- let widowW = document.body.clientWidth;
- let windowH = document.body.clientHeight;
- //console.log(widowW);
- //通过事件委托,计算移动的距离
- let l = touches.clientX - disX;
- let t = touches.clientY - disY;
- if(l <= 0) {
- l = 0;
- } else if(l > document.documentElement.clientWidth - oDiv.offsetWidth) {
- l = document.documentElement.clientWidth - oDiv.offsetWidth;
- }
- if(t <= 0) {
- t = 0;
- } else if(t > document.documentElement.clientHeight - oDiv.offsetHeight - footerH) {
- t = document.documentElement.clientHeight - oDiv.offsetHeight - footerH;
- }
- //移动当前元素
- oDiv.style.left = l + 'px';
- oDiv.style.top = t + 'px';
- event.preventDefault(); //阻止冒泡
- // 可注释start 将此时的位置传出去 ,这一段,可以注释,是传输位置坐标的
- binding.value({
- x: touches.pageX,
- y: touches.pageY
- })
- // 可注释end
- });
- oDiv.addEventListener('touchend', function(e) {
- document.ontouchmove = null;
- document.ontouchend = null;
- });
- });
- }
- }
- }
- }
- </script>
实例:拖拽排序 + 上下按键排序
XML/HTML Code复制内容到剪贴板
- <div class="clear plan-list" v-if="selectedLessonList.length">
- <draggable v-model="selectedLessonList" @end="dropEnd">
- <ul v-for="(item,index) in selectedLessonList" :data-id="item.value" :key="item.value">
- <li>
- <i class="control-icon up-icon" @click="sort(index,0)"></i>
- <i class="control-icon down-icon" @click="sort(index,1)"></i>
- <span>{{item.label}}</span>
- <i class="fr delete-icon" aria-hidden="true" @click="delSelectedLesson(item.value)"></i>
- </li>
- </ul>
- </draggable>
- </div>
JavaScript Code复制内容到剪贴板
- <script>
- import draggable from 'vuedraggable'
- import teachPlanChooseLesson from '@/components/common/addCourse/teachPlanChooseLesson.vue'
- export default {
- name: 'teachPlanForm',
- data() {
- return {
- popupVisible: false, //弹出层默认关闭
- teach_title: '', //标题
- selectedLessonList: [], //已选择的课程数组
- selectedLessonIds: [], //已选择的课程ID数组
- linkId: "", //关联ID
- }
- },
- props: ['planId'],
- components: {
- chooseLesson: teachPlanChooseLesson,
- draggable
- },
- mounted() { // 这个是页面创建的时候,就执行相关的方法
- this.init()
- },
- methods: {
- selectedLesson(selected, ids) {
- // 监听子层的选择课程库,重新渲染dom,并且存储已选择的id
- this.selectedLessonIds = ids;
- this.$set(this, "selectedLessonList", selected);
- },
- delSelectedLesson(id) {
- // 删除已选择的课时,同时传输给子层
- this.removeByValue(this.selectedLessonList, id); //删除v-for中的其中一组
- this.removeByKey(this.selectedLessonIds, id); //删除给子层和接口用的ids
- this.$set(this, "selectedLessonList", this.selectedLessonList); //重新渲染列表
- },
- removeByValue(arr, val) {
- // 查询value中是否有这个值,如果有就去除这个数组
- for(var i = 0; i < arr.length; i++) {
- if(arr[i].value == val) {
- arr.splice(i, 1);
- break;
- }
- }
- },
- removeByKey(arr, val) {
- // 查询key中是否有这个值,如果有就去除这个数组
- for(var i = 0; i < arr.length; i++) {
- if(arr[i] == val) {
- arr.splice(i, 1);
- break;
- }
- }
- },
- submitForm() {
- //提交表单
- let newItems = [];
- this.selectedLessonList.forEach(function(item) {
- newItems.push(item.value);
- });
- let lessonList = newItems ? newItems.join(",") : ""; // 拖拽排序的那一组数据,抽取它的ID组成新的值给后端
- },
- dropStart() {
- // console.log("开始拖动");
- },
- dropEnd(evt) {
- // 拖动结束后重组 传给接口的id
- //console.log(newItems);
- },
- //点击排序
- sort(key, status) {
- let allData = this.selectedLessonList;
- if(status) {
- if(key != (allData.length - 1)) { //index等于最大下不去
- let items //临时变量
- items = allData[key + 1];
- allData[key + 1] = allData[key];
- allData[key] = items;
- this.$nextTick(function () {
- this.selectedLessonList = [];
- this.selectedLessonList = allData;
- })
- }
- } else {
- if(key) { //key=0上不去
- let temp = ""; //临时变量
- temp = allData[key - 1];
- allData[key - 1] = allData[key];
- allData[key] = temp;
- this.$nextTick(function () {
- this.selectedLessonList = [];
- this.selectedLessonList = allData;
- })
- }
- }
- }
- }
- }
- </script>
上一篇 vue css,js引入方式
下一篇 vue v-if