小程序封装拖拽菜单组件(uniapp拖拽排序,自定义菜单)

您所在的位置:网站首页 vue移动端h5拖拽排序实现 小程序封装拖拽菜单组件(uniapp拖拽排序,自定义菜单)

小程序封装拖拽菜单组件(uniapp拖拽排序,自定义菜单)

2023-10-09 01:56| 来源: 网络整理| 查看: 265

效果展示

在这里插入图片描述

思路 使用movable-area作为可移动区域,并在内部循环渲染列表项view,绑定touch事件。在mounted生命周期函数内获取区域movable-area的dom信息,记录列表项的坐标信息。在methods中定义了列表项的touchstart、touchmove和touchend事件的方法,用于实现列表项的拖拽移动和位置变更。watch监听列表项数据listData的变化,并抛出事件,通知列表变更。 具体步骤 1, 在components文件夹新建healer-dragList文件夹,在healer-dragList文件夹下新建AppList.vue组件

在这里插入图片描述

使用movable-area创建一个可移动区域容器

movable-area 是 uniapp 的可移动区域组件。它用于定义可移动视图容器,在其内部可拖拽移动子视图。 在 movable-area 组件中,可以使用 movable-view 组件定义可移动的子视图。movable-view 必须是 movable-area 的直接子节点,不支持嵌套 movable-view。

movable-area 的属性有:

scale - 手势缩放比例,默认为1, 范围0~10direction - 可移动方向,值有 ‘all’,‘vertical’,‘horizontal’,‘none’ movable-view 的属性有:direction - 可移动方向,同 movable-area 的 directioninertia - 是否启用滚动惯性,默认falseoutOfBounds - 超出可移动区域后,movable-view 的行为,可选值有 ‘none’、‘hidden’、‘bounce’x/y - movable-view 的位置damping - 阻尼系数,用于控制x或y变化的动画和过界回弹的衰减速度。取值范围[0, 1]。friction - 摩擦系数,用于控制x或y变化的动画和过界回弹的摩擦力。取值范围[0, 1]。

movable-area 和 movable-view 通常搭配使用,来实现可拖拽排序的列表效果。

在这里插入图片描述 //AppList.vue

{{appItem.appName}} {{touchItem.appName}} // import InputUnify from "@/components/unify-input.vue" export default { name: "AppList", props: { listData: { type: Array, default: () => { return [] } }, isEdti: { type: Boolean, default: false } }, data() { return { listData_c: this.listData, //缓存props,(不建议直接修改props) // CheckAppId: null, deleteAppID: null, //触发删除的itemID showDelete: false, //删除按钮状态 IsDeleteAfter: false, //是否为删除后 IsCancelDelete: false, //是否为取消后 moviewShow: false, //滑块状态 areaBoxInfo: null, //保存滑动区域盒子dom信息 inBoxXY: {}, //鼠标在item中的坐标 touchIndex: 0, //被移动index touchItem: '', //备份被移动item数据 moveX: 0, //相对滑动盒子的坐标 moveY: 0, //相对滑动盒子的坐标 hoverClass: '', hoverClassIndex: null, //最终index }; }, watch: { listData_c(val) { this.$emit("listChange", val) } }, computed: { moveViewSize() { if (this.areaBoxInfo && this.areaBoxInfo.width) { return this.areaBoxInfo.width / 5 } else { return 0 } } }, components: { // InputUnify }, mounted() { // 获取dom信息 this.resetListDom() }, methods: { dleIcon(a, b) { this.$emit("lowAppList", a); }, getDomInfo(id, callBack) { const query = uni.createSelectorQuery().in(this); query.select('#' + id) .boundingClientRect() .exec(function(res) { callBack(res[0]); }); }, // 添加 addAppItem() { this.$refs.addAppItem.ModalStatus() }, confirm() { let appItem = { appId: this.listData_c.length + 1, appIcon: "cuIcon-pic", appName: this.$refs.addAppInput.value, appLink: "" }; this.listData_c.push(appItem); this.$refs.addAppInput.resetVal(); this.$nextTick(() => { this.resetListDom() }); }, AppLi_touchstart(index, event) { this.touchItem = this.listData_c[index]; // 行为判断 if (this.showDelete) { // 取消删除 if (this.touchItem.appId != this.deleteAppID) { this.deleteAppID = null; this.showDelete = false; this.IsCancelDelete = true; } // 删除 // if(this.touchItem.appId==this.deleteAppID){ // this.deleteAppItem(index) // } } // 过时触发(touchEnd中清除此定时器) this.Loop = setTimeout( () => { // 触感反馈(安卓上是150毫秒,ios无短触控反馈) uni.vibrateShort(); this.showDelete = true; this.deleteAppID = this.touchItem.appId; // 拖动逻辑 //显示可移动方块 this.moviewShow = true //保存当前所选择的索引 this.touchIndex = index; // 设置可移动方块的初始位置为当前所选中图片的位置坐标 this.moveX = this.listData_c[index].x; this.moveY = this.listData_c[index].y; var x = event.changedTouches[0].clientX - this.areaBoxInfo.left; var y = event.changedTouches[0].clientY - this.areaBoxInfo.top; // 保存鼠标在图片内的坐标 this.inBoxXY = { x: x - this.listData_c[index].x, y: y - this.listData_c[index].y, } }, 500); }, AppLi_touchmove(event) { // 每次endTouch清除startTouch删除按钮定时器 if (this.Loop) { clearTimeout(this.Loop); this.Loop = null; } if (this.showDelete) { let areaBoxTop = this.areaBoxInfo.top; let areaBoxLeft = this.areaBoxInfo.left; //重置为以拖拽盒子左上角为坐标原点 var x = event.changedTouches[0].clientX - areaBoxLeft; var y = event.changedTouches[0].clientY - areaBoxTop; this.moveX = x - this.inBoxXY.x; this.moveY = y - this.inBoxXY.y; let setIng = false; this.listData_c.forEach((item, idx) => { if (x > item.x && x item.y && y this.hoverClass = "" this.hoverClassIndex = null; } } }, AppLi_touchend(index) { if (!this.showDelete && !this.IsDeleteAfter && !this.IsCancelDelete) { this.getInto(this.touchItem) } else { // 为下次getInto清除状态 this.IsDeleteAfter = false; this.IsCancelDelete = false; // 移动结束隐藏可移动方块 if (this.hoverClassIndex != null && this.touchIndex != this.hoverClassIndex) { this.$set(this.listData_c, this.touchIndex, this.listData_c[this.hoverClassIndex]); this.$set(this.listData_c, this.hoverClassIndex, this.touchItem); this.showDelete = false; this.resetListDom() } this.touchItem = "" this.moviewShow = false this.hoverClass = "" this.hoverClassIndex = null; } // 每次endTouch清除startTouch删除按钮定时器 if (this.Loop) { clearTimeout(this.Loop); this.Loop = null; } }, deleteAppItem(index) { this.listData_c.splice(index, 1) this.showDelete = false; this.checkIndex = null; this.IsDeleteAfter = true; this.resetListDom() }, getInto(e) { if (e.appName == '更多') { return; } if (this.isEdti) return; uni.navigateTo({ url: e.appLink, }) }, resetListDom() { let _this = this; this.getDomInfo('areaBox', info => { _this.areaBoxInfo = info; // 设置区域内所有图片的左上角坐标 _this.listData_c.forEach((item, idx) => { _this.getDomInfo('appLi' + idx, res => { item.x = res.left - info.left; item.y = res.top - info.top; }); }); }); }, boxClick() { this.deleteAppID = null; this.showDelete = false; } } } .rightIcon { position: absolute; right: 5rpx; top: -10rpx; } .movarea { width: 100%; height: auto; } .appList { width: 100%; display: flex; flex-wrap: wrap; } .app-li { width: 20%; // height: 160rpx; text-align: center; display: flex; flex-direction: column; justify-content: space-around; position: relative; margin-bottom: 30rpx; .appIcon { font-size: 60rpx; width: 50%; margin: 0 auto; } .appName { font-size: 24rpx; } .cuIcon-roundadd { font-size: 60rpx; color: #CCCCCC; } .cuIcon-roundclosefill { position: absolute; top: 12rpx; right: 12rpx; font-size: 36rpx; z-index: 2; &.hide { display: none; } } } .moveV { opacity: 0.8; z-index: 999; width: 100rpx; height: 160rpx; box-sizing: border-box; text-align: center; display: flex; flex-direction: column; justify-content: space-around; padding: 20rpx; .appIcon { font-size: 60rpx; width: 100%; } .appName { font-size: 24rpx; } } .select { // transform: scale(1.3); border-radius: 16rpx; border: 1px dashed #C0C0C0; color: #C0C0C0; } 2, 在所需页面引用AppList.vue组件 点击下方【编辑】按钮,可调整首页功能展示 长按图标可调整首页图标展示顺序 首页已展示功能 其他功能 {{appItem.appName}} 完成 编辑 import AppList from "@/components/healer-dragList/AppList.vue" export default { data() { return { isEdti: false, //这里写你自己页面路由信息 appListData: [{ appId: 0, appName: '示例菜单跳转页面', appIcon: '/static/img/category/invitation.png', appLink: "/pagesA/inviteAgents/inviteAgents" }], } }, components: { AppList, }, onLoad() { }, onShow() { if (!uni.getStorageSync('MENU_DATA')) { // this.getUseInfoData() console.log('') } else { let data = uni.getStorageSync('MENU_DATA') this.appListData = JSON.parse(data) } if (!uni.getStorageSync('MENU_BTM_DATA')) { // this.getUseInfoData() console.log('') } else { let data = uni.getStorageSync('MENU_BTM_DATA') this.autherData = JSON.parse(data) } }, methods: { goAuther(e) { if (e.appName == '更多') { return; } try { uni.navigateTo({ url: e.appLink }) } catch (err) { uni.showToast({ title: '当前模块正在开发...', icon: 'none' }) } }, setMenuStor() { this.isEdti = false uni.setStorageSync('MENU_DATA', JSON.stringify(this.appListData)) uni.setStorageSync('MENU_BTM_DATA', JSON.stringify(this.autherData)) }, //菜单上到下 lowAppListData(e) { if (this.appListData[e].appName == '更多') { uni.showToast({ title: '更多不能被移出首页', icon: 'none' }) return } this.autherData.push(this.appListData[e]) this.appListData.splice(e, 1) }, addIcon(index) { if (this.appListData.length == 10) { uni.showToast({ title: '首页菜单不能大于10个', icon: 'none', duration: 2000 }) return; } this.appListData.push(this.autherData[index]) this.autherData.splice(index, 1) }, listChange(option) { console.log("listChange", option) } } } .rightIcon { position: absolute; right: 5rpx; top: -10rpx; } .btmBox { position: absolute; bottom: 0; width: 100%; height: 80rpx; line-height: 80rpx; background: #427ce7; text-align: center; color: white; } .appList { width: 100%; display: flex; flex-wrap: wrap; } .app-li { width: 20%; // height: 160rpx; text-align: center; display: flex; flex-direction: column; justify-content: space-around; position: relative; margin-bottom: 30rpx; .appIcon { font-size: 60rpx; width: 50%; margin: 0 auto; } .appName { font-size: 24rpx; } .cuIcon-roundadd { font-size: 60rpx; color: #CCCCCC; } .cuIcon-roundclosefill { position: absolute; top: 12rpx; right: 12rpx; font-size: 36rpx; z-index: 2; &.hide { display: none; } } } .topText { color: #427ce7; font-size: 30rpx; text-align: center; padding: 50rpx; } .content { background-color: #ffffff; } .title { padding: 30rpx; color: #808fb4; } 总结

以上代码实现了uniapp在小程序端实现菜单拖拽排序,以及显示隐藏指定菜单功能,有点小bug,需要原始代码的可以给我私信留言。当然有更简单的办法 uni-app切片工具也可以实现拖拽排序、菜单排序、导航排序等更多功能!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3