当前位置: 首页 > article >正文

uniapp结合movable-area与movable-view实现拖拽功能2

前言

上篇我们写了,固定高度的拖拽,这篇我们将进行不固定高度的拖拽模块编写完成。

开始

一、初始化

我们在list数组里面增加一个data的动态数组,这样可以动态改变元素的高度。

当前元素y = 上一个元素的高度

<template>
  <view style="height: 100%;">
    <movable-area :style="{'width': '100%', 'height': allHeight + 'px'}">
      <movable-view
        v-for="(item, index) in list"
        :key="item.id"
        :x="0"
        :y="item.y"
		:style="{'height': item.itemHeight + 'px', 'width': '100%',}"
        direction="all"
        @touchstart="handleDragStart(index)"
	   @change="handleMoving(index, $event)"
	   @touchend="handleDragEnd"
        class="movable-view"
      >
	  
        <!-- 这里可以放置步骤的详细内容 -->
        <view style="background-color: aqua; padding: 20rpx 0; margin: 10rpx 0;">
			<view v-for="(d_item, d_key) in item['data']" :key="d_key">{{ d_item.name }}</view>
		</view>
		
      </movable-view>
    </movable-area>
  </view>
</template>
 
<script>
export default {
  data() {
    return {
		list: [],
		allHeight: 0,
    };
  },
  
  created() {
	  // 初始化 === 当前y=上一个元素高度(索引为0的y=0)
	  this.list = [
		  {
			  id: 0,
			  itemHeight: 100,
			  y: 0,
			  key: Math.random() + 0,
			  data: [
				  {
					name: '测试0-1'
				  },
				  {
					name: '测试0-2'
				  }
			  ]
		  },
		  {
			  id: 1,
			  itemHeight: 50,
			  y: 100,
			  key: Math.random() + 1,
			  data: [
				  {
					name: '测试1-1'
				  }
			  ]
		  },
		  {
			  id: 2,
			  itemHeight: 50,
			  y: 150,
			  key: Math.random() + 2,
			  data: [
				  {
					name: '测试2-1'
				  }
			  ]
		  },
		  {
			  id: 3,
			  itemHeight: 200,
			  y: 200,
			  key: Math.random() + 3,
			  data: [
				  {
					name: '测试3-1'
				  },
				  {
					name: '测试3-2'
				  },
				  {
					name: '测试3-3'
				  },
				  {
					name: '测试3-4'
				  }
			  ]
		  },
	  ]
	  
  },
  
  methods: {
  },
};
</script>
 
<style>
.movable-area {
 
}
 
.movable-view {
 
}
</style>

二、拖拽实现

y是高度累加,通过ref获取元素高度

<template>
	<view style="height: 100%;">
		<movable-area :style="{'width': '100%', 'height': allHeight + 'px'}">
			<movable-view v-for="(item, index) in list" :key="item.id" :x="0" :y="item.y"
				:style="{'height': item.itemHeight + 'px', 'width': '100%', 'background-color': '#fff'}" direction="all"
				@touchstart="handleDragStart(index)" @change="handleMoving(index, $event)" @touchend="handleDragEnd"
				class="movable-view">

				<!-- 这里可以放置步骤的详细内容 -->
				<view ref="itemRef" style="background-color: aqua; height: 100%; margin: 10rpx 0;">
					<view v-for="(d_item, d_key) in item['data']" :key="d_key">{{ d_item.name }}</view>
				</view>

			</movable-view>
		</movable-area>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				list: [],
				cloneList: [],

				activeIndex: -1, // 选中
				oldIndex: -1,

				moveToIndex: -1, // 移动

				allHeight: 1200,
			};
		},
		mounted() {
			// console.log("===itemRef===", this.$refs.itemRef);
			// if (this.$refs.itemRef) {
			// 	this.$refs.itemRef.forEach((item) => {
			// 		console.log(item.$el.clientHeight)
			// 	});
			// }
		},
		created() {
			// 1.通过ref获取元素高度,并进行计算y轴
			// 2.拖拽时,更换位置(重新计算-高度累积计算)

			// 注意点(总高度不够时,会乱排序)

			// 初始化
			this.list = [{
					id: 0,
					y: 0,
					itemHeight: 100,
					data: [{
							name: '测试0-1'
						},
						{
							name: '测试0-2'
						}
					]
				},
				{
					id: 1,
					y: 100,
					itemHeight: 50,
					data: [{
						name: '测试1-1'
					}]
				},
				{
					id: 2,
					y: 150,
					itemHeight: 50,
					data: [{
						name: '测试2-1'
					}]
				},
				{
					id: 3,
					y: 200,
					itemHeight: 200,
					data: [{
							name: '测试3-1'
						},
						{
							name: '测试3-2'
						},
						{
							name: '测试3-3'
						},
						{
							name: '测试3-4'
						}
					]
				},
			];

			this.cloneList = this.deepCopy(this.list);
		},

		methods: {
			deepCopy(source) {
				return JSON.parse(JSON.stringify(source));
			},

			// 拖拽开始
			handleDragStart(index) {
				this.activeIndex = index;
				this.oldIndex = index;
			},
			handleMoving(index, e) {
				if (e.detail.source !== 'touch') return;
				const {x, y} = e.detail;
				
				let itemHeight = this.list[index]['itemHeight'];
				const currentY = Math.floor((y + itemHeight / 2) / itemHeight);
	
				this.moveToIndex = Math.min(currentY, this.list.length - 1);
				// console.log("===this.moveToIndex===", this.moveToIndex);
			},
			handleDragEnd(e) {
				console.log("=====拖拽结束============");
				if (this.moveToIndex !== -1 && this.activeIndex !== -1 && this.moveToIndex !== this.activeIndex) {
					
					// console.log("===选中目标activeIndex===", this.list[this.activeIndex]);
					// console.log("===移动目标moveToIndex===", this.list[this.moveToIndex]);
					
					// 交互位置
					this.cloneList.splice(this.moveToIndex, 0, ...this.cloneList.splice(this.activeIndex, 1));
					// 计算y轴
					this.cloneList.forEach((item) => {
						item.y = currentY;
      					currentY += item.itemHeight;
					});
					this.list = this.cloneList
				}
				this.activeIndex = -1;
				this.oldIndex = -1;
				this.moveToIndex = -1;
			},
		},
	};
</script>

<style>
	.movable-area {}

	.movable-view {}
</style>


http://www.kler.cn/a/488682.html

相关文章:

  • 高级软件工程-复习
  • 宝塔安装mongodb后,写脚本监控运行状态,关闭后自动重启
  • “深入浅出”系列之QT:(6)如何在一个项目中调用另一个项目
  • (概率论)无偏估计
  • 掌握正则表达式:从入门到精通的实战指南
  • 【杂谈】-50+个生成式人工智能面试问题(一)
  • Hbuilder ios 离线打包sdk版本4.36,HbuilderX 4.36生成打包资源 问题记录
  • wireshark排除私接小路由
  • MT6835天玑6100平台规格参数_MTK联发科安卓核心板方案定制开发
  • 【MFC】设置CTreeCtrl单个节点的文字颜色
  • Jenkins git SSH获取code报错:git@github.com: Permission denied (publickey).
  • 计算机网络 (33)传输控制协议TCP概述
  • 【HTML+CSS+JS+VUE】web前端教程-18-css引入方式
  • 2025年第三届“华数杯”国际赛B题解题思路与代码(Matlab版)
  • 网络安全测评技术与标准
  • LeetCode:2274. 不含特殊楼层的最大连续楼层数(排序 Java)
  • smplx blender插件笔记
  • 甘蔗叶片图像元素含量的回归预测多模型实现【含私人数据集】
  • Windows 程序设计2:第一个Windows实例程序
  • 什么是数据湖?大数据架构的未来趋势
  • C++ 中的 template <typename T> 用法 ← 泛型
  • 【UE5 C++课程系列笔记】23——多线程基础——AsyncTask
  • vscode开启调试模式,结合Delve调试器调试golang项目详细步骤
  • 每日算法Day14【删除二叉搜索树中的节点、修剪二叉搜索树、将有序数组转换为二叉搜索树、把二叉搜索树转换为累加树】
  • PHP 循环控制结构深度剖析:从基础到实战应用
  • 后端技术选型 sa-token校验学习 上 登录校验复习