基于movable-view的微信小程序拖拽排序(含源码)

这篇具有很好参考价值的文章主要介绍了基于movable-view的微信小程序拖拽排序(含源码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、前言与效果展示

二、源码

1.目录结构

2.drag.wxml文件

3.drag.wxss文件

(1)drag.less

(2)drag.wxss  不会使用less的就用这个

4.drag.js文件

5.drag.json文件

三、结语


一、前言与效果展示

        最近在做一个账本,里面有个功能需要“拖拽排序”,网上的代码我也看不太懂,打算自己写一个。微信小程序官方给了一个可移动的盒子 movable-view ,基于这个我们来实现一个简单的拖拽排序功能

效果: 可以自定义一行展示多少个图标,下面演示一行五个的情况

微信小程序拖拽上下排序,微信小程序,前端,微信小程序,小程序,javascript

二、源码

1.目录结构

我起名为drag,你们可以自己选择起名

微信小程序拖拽上下排序,微信小程序,前端,微信小程序,小程序,javascript

2.drag.wxml文件

(1)使用了wxs定义了parseInt函数 (因为在模板中不能直接使用parseInt(),需要借助wxs)

(2)movable-view中,除了class为showLine的元素不要动,其它的比如icon和name可以自定义样式删除或修改 (showLine是用于元素拖拽时的位置提示)

(3)movable-view标签的 style 里,有个background-color,你们可以自己选择颜色,用于“被拖拽的元素”的背景颜色

<wxs module="m1">
  var parseIntNumber = function (num) {
    return parseInt(num)
  }
  module.exports.parseIntNumber = parseIntNumber;
</wxs>
<view class="list">
  <movable-area class="moveList" style="height: {{(m1.parseIntNumber(positionList.length/drag.countOneLine)+1) * (drag.height)}}rpx;width: {{drag.outWidth}}rpx;">
    <movable-view wx:for="{{positionList}}" wx:key="id" out-of-bounds direction="all" style="height: {{drag.height}}rpx;width: calc({{drag.outWidth}}rpx / {{drag.countOneLine}});background-color: {{nowDragIndex == index ? '#bbbbbb90':''}};" class="moveItem" x="{{positionList[index].left}}rpx" y="{{positionList[index].boxTop}}rpx" bindchange="drag" bindtouchend="dragEnd" data-myindex="{{index}}">
      <!-- 蓝色边边的出现条件:当前轮到index这个索引显示了 且 当前拖动的元素的索引不是index -->
      <view class="showLine" wx:if="{{ showLine === index && nowDragIndex!==index}}"></view>
      <view class="icon">图标</view>
      <view class="name">{{item.name}}</view>
    </movable-view>
  </movable-area>
</view>

3.drag.wxss文件

我是使用less写的样式文件,所以这里会放less 的源代码,不会使用less 的请看 (2)drag.less

movable-view自动具有绝对定位属性,只能通过标签里的x和y来定位,无法使用flex布局

(1)drag.less

.list {
  display: flex;
  flex-wrap: wrap;

  .moveList {
    width: 100%;

    .moveItem {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      background-color: #ececec00;

      .icon {
        height: 60rpx;
        width: 60rpx;
        line-height: 60rpx;
        text-align: center;
        font-size: 20rpx;
        background-color: aqua;
        border-radius: 50%;
      }

      .showLine {
        position: absolute;
        left: 0;
        transform: translate(-50%);
        width: 10rpx;
        height: 100%;
        background-color: blue;
      }
    }

  }
}

(2)drag.wxss  不会使用less的就用这个

.list {
  display: flex;
  flex-wrap: wrap;
}
.list .moveList {
  width: 100%;
}
.list .moveList .moveItem {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: #ececec00;
}
.list .moveList .moveItem .icon {
  height: 60rpx;
  width: 60rpx;
  line-height: 60rpx;
  text-align: center;
  font-size: 20rpx;
  background-color: aqua;
  border-radius: 50%;
}
.list .moveList .moveItem .showLine {
  position: absolute;
  left: 0;
  transform: translate(-50%);
  width: 10rpx;
  height: 100%;
  background-color: blue;
}

4.drag.js文件

在data里的drag对象中,可以自定义 盒子的高度、每一行展示的个数、可移动区域的宽度

想拖拽排序的数据放在 list 里面,注意需要有id,用于wx:for的key值

注:movable-view 的拖拽事件 bindchange 的e.detail中的数据,单位是px,需要转为rpx才能和我们写的单位匹配

// pages/drag/drag.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    drag: { //控制拖拽部分的盒子大小,在这里输入初始数据
      outWidth: 750, //可移动区域的宽度,单位rpx,750rpx是屏幕宽度
      height: 120, //盒子的高度,单位rpx
      countOneLine: 5, //一行盒子的个数,这个决定盒子宽度 (outWidth / countOneLine)
    },
    list: [ //列表,在这里输入想展示的数据,最后将会修改这里的顺序
      {
        id: 0, // id
        name: '餐饮', //名称
      },
      {
        id: 1, // id
        name: '交通', //名称
      },
      {
        id: 2, // id
        name: '住房', //名称
      },
      {
        id: 3, // id
        name: '美容', //名称
      },
      {
        id: 4, // id
        name: '服饰', //名称
      },
      {
        id: 5, // id
        name: '运动', //名称
      },
      {
        id: 6, // id
        name: '旅行', //名称
      },
      {
        id: 7, // id
        name: '娱乐', //名称
      },
      {
        id: 8, // id
        name: '生活', //名称
      },
      {
        id: 9, // id
        name: '医疗', //名称
      },
      {
        id: 10, // id
        name: '通讯', //名称
      },
      {
        id: 11, // id
        name: '学习', //名称
      },
      {
        id: 12, // id
        name: '礼物', //名称
      },
      {
        id: 13, // id
        name: '亲属', //名称
      },
      {
        id: 14, // id
        name: '数码', //名称
      },
      {
        id: 15, // id
        name: '零食', //名称
      },
      {
        id: 16, // id
        name: '购物', //名称
      },
      {
        id: 17, // id
        name: '其它', //名称
      },
      {
        id: 18, // id
        name: '转换', //名称
      },
      {
        id: 19, // id
        name: '出门', //名称
      },
      {
        id: 20, // id
        name: '红包', //名称
      },
      {
        id: 21, // id
        name: '食堂', //名称
      },
      {
        id: 22, // id
        name: '外卖', //名称
      },
      {
        id: 23, // id
        name: 'AA', //名称
      },
      {
        id: 24, // id
        name: '超市', //名称
      },
      {
        id: 25, // id
        name: '水电', //名称
      },
      {
        id: 26, // id
        name: '早餐', //名称
      },
      {
        id: 27, // id
        name: '水果', //名称
      },
      {
        id: 28, // id
        name: '借款', //名称
      },
    ],
    positionList: [], //把list转化后,具有定位数据的列表(展示在页面上)
    //下面的是一些动态的索引
    showLine: -1, //显示哪个索引的蓝色线
    nowDragIndex: -1, //当前拖动的索引
  },

  //拖拽时触发
  drag(e) {
    if (e.detail.source == '') return //如果这个值为空,说明不是手动拖拽的,不要进行下面的操作
    // console.log(e.detail);


    let myindex = e.currentTarget.dataset.myindex //当前拖动的图标的index
    if (this.data.nowDragIndex !== myindex) { //设置当前拖动的图标
      console.log('当前拖动的图标序号为', myindex);
      this.setData({
        nowDragIndex: myindex
      })
    }

    // e.detail单位是px,需要转为rpx
    let x = this.pxToRpx(e.detail.x) //转为rpx的x
    let y = this.pxToRpx(e.detail.y) //转为rpx的y
    let box = {}
    let drag = this.data.drag //拖拽部分的变量 宽 高 个数等
    box.leftX = x //正在拖动的盒子的左侧x值
    box.rightX = x + drag.outWidth / drag.countOneLine //正在拖动的盒子的右侧x值
    box.topY = y //正在拖动的盒子的顶部y值
    box.bottomY = y + drag.height //正在拖动的盒子的底部y值

    //使用for循环判断现在正在哪个位置 - 性能问题,如何防抖?
    for (let i = 0; i < this.data.positionList.length; i++) {
      const element = this.data.positionList[i];
      //判断拖拽的盒子,在哪个蓝色模块的位置
      if (box.leftX < element.left && box.rightX > element.left && element.boxTop - 20 < box.topY && element.boxBottom + 20 > box.bottomY) {
        this.setData({
          showLine: i
        })
        break
      }
    }

  },

  //拖拽的结束,判断是否应该移动,还是回复原位
  dragEnd(e) {
    let newIndex = this.data.showLine //即将挪动到的位置
    let nowDragIndex = this.data.nowDragIndex //原本的位置
    if (newIndex >= 0 && nowDragIndex !== newIndex) { //给showline赋值了且不是自己,说明需要变化位置
      console.log('需要变化位置');
      let newList = this.data.list //改变的是list,而不是页面展示的positionList
      let item = newList.splice(nowDragIndex, 1) // 删除指定的元素,给item
      newList.splice(newIndex, 0, item[0]) // 把item添加到指定位置

      this.setData({
        list: newList, //data的list修改,方便接下来重新计算位置
      })
      //然后刷新页面,重新计算position
      this.countPosition()

    } else {
      console.log('拖了但没完全拖,回复原位');
      setTimeout(() => {//使用定时器,防止拖拽到边缘时,无法正常归位(等待边缘动画结束后再回复原位,这个好像是微信小程序这个组件的bug,搜到了三个月前的bug,到现在还没解决)
        this.setData({
          positionList: this.data.positionList, //回复原位
        })
      }, 300);
    }
    //重置索引
    this.setData({
      showLine: -1,
      nowDragIndex: -1,
    })
    console.log(this.data);
  },



  //计算list里每个数据的坐标,放到positionList里
  countPosition() {
    let positionList = [] //装着列表的坐标数据
    let list = this.data.list
    for (let i = 0; i < list.length; i++) {
      let element = list[i]
      positionList.push({
        ...element,
        index: i,
        left: (i % this.data.drag.countOneLine) * (this.data.drag.outWidth / this.data.drag.countOneLine),
        boxTop: parseInt(i / this.data.drag.countOneLine) * this.data.drag.height,
        boxBottom: (parseInt(i / this.data.drag.countOneLine) + 1) * this.data.drag.height,
      })
    }
    this.setData({
      positionList
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {

    //#region 定义 px转rpx 函数
    wx.getSystemInfo({
      success: (result) => {
        this.windowWidth = result.windowWidth
      },
    })
    this.pxToRpx = function (v_px) {
      let onePxToRpx = 750 / this.windowWidth
      return v_px * onePxToRpx
    }
    //#endregion

    //#region 计算列表的坐标, 装着列表的数据,包含坐标
    this.countPosition()
    //#endregion

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

5.drag.json文件

无需改动,是默认的即可

{
  "usingComponents": {}
}

三、结语

        本次源码分享到这里结束,由于这是我花三个小时写出来的,肯定存在很多不足,比如在拖拽函数中,判断元素应该被挪动到的位置,我用了for循环来一个个判断,这必定会影响到性能 (因为微信提供的这个拖拽函数,只要盒子稍微移动一点点,都会触发很多次,再加上里面还有for循环,会造成短时间内有多个for循环在运行) 所以建议在数据量不大的时候可以使用这个源码,数据量很大的时候会卡顿。

        除此之外,微信小程序这个组件有个自带的bug,当拖拽到边缘时,想动态设置x和y值,此时x可以被正常设置,但是y值不可以。就会出现:本来拖拽到无效区域,应该跑回原本的位置的,但是x值回去了,y值没回去,导致这样微信小程序拖拽上下排序,微信小程序,前端,微信小程序,小程序,javascript这是页面显示效果的问题,不影响排序功能。

        如果你有更好的解决方式,欢迎在评论区里不吝赐教!文章来源地址https://www.toymoban.com/news/detail-772080.html

到了这里,关于基于movable-view的微信小程序拖拽排序(含源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序缩放图片与滑动图片:movable-view与swiper一起使用所产生的手势冲突的基本解决方案(操作过于频繁还是会出现问题,基本的使用是没有问题的)

    1.一些参数和需要用到的方法js代码注释都有了,只要复制过去看就好了 2.怎么解决这个手势冲突呢,我采用的是mina-touch插件,去监听这两种手势,当双指在的时候,长按事件就不触发,滑动的时候长按事件也要阻止,因为在不停的滑动的时候,也会长按,大概就是这么一个

    2024年02月15日
    浏览(54)
  • 滑动验证组件---设置movable-view组件的x属性在微信小程序端失效的问题

    采用uniapp的movable-view组件实现滑动验证组件。 流程 滑块未滑到最右端时,回弹到原点 滑块滑到最右端时,则显示滑动结束,不可再滑动 频繁设置uniapp的movable-view组件的x属性,在H5端正常,但在微信小程序端则失效。 index.vue woSlider.vue H5端 微信小程序端 官方给出的解释: 由

    2024年02月11日
    浏览(35)
  • 基于若依框架的微信小程序登录

    一、用户表结构 二、用户实体类 三、登录时用到的SQL语句 四、微信用户登录验证 五、创建token令牌 六、登录接口涉及方法

    2024年02月11日
    浏览(42)
  • 基于uniapp的微信小程序如何刷新页面(绝对有效)

    由于我的毕业设计就是用uniapp写的微信小程序。 碰到了这样的问题,查了许多资料,最终找到了这样的方法。 现在写出来给大家节约时间和精力。 就是用uni.redirectTo 实现页面跳转从而实现页面刷新 注意:这不能刷新tabBar页面 不要傻乎乎的用在tabBar上 跳转到tabBar页面只能使

    2024年02月11日
    浏览(57)
  • 基于SSM的微信小程序农业信息服务平台

    近年来,随着农业经济的不断发展,通过农贸市场等方式交易农产品的模式已经无法满足农业经济发展的需要,为了提高农产品的交易率,降低经营成本,利用计算机技术,构建一个基于SSM的微信小程序农业信息服务平台,方便农户、采购者等用户之间农产品交易以及农业相

    2024年01月22日
    浏览(51)
  • 基于SpringBoot+Vue+uniapp微信小程序的微信小程序书店的详细设计和实现

    💗 博主介绍 :✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻 精彩专栏 推荐订阅 👇🏻 2023-2024年最值得选的微信小程序毕业设

    2024年03月17日
    浏览(78)
  • 基于uniapp的微信小程序学生信息选课系统[源码+远程+答疑

     网站介绍:✌本网站专注专注于计算机技术领域的毕业设计辅导,提供JAVA、微信小程序、Python、APP、PHP、微服务、NET等毕设项目的定制和成品服务!✌         ✌IT实战营站长,拥有10年软件相关系统架构及教学经验,Java、大数据培训讲师,曾任公司技术总监;其与团队

    2024年01月24日
    浏览(88)
  • 基于 Taro 框架的微信小程序 canvas 绘图海报组件

    项目需要保存收款码,效果如图: (此文仅代表个人日常工作记录,能力有限描述并不全面) 1.安装 npm i taro-plugin-canvas -S --production(taro-plugin-canvas 是基于 Taro 框架的微信小程序 canvas 绘图组件,封装了常用的操作,通过配置的方式生成分享图片)  2.引入:import { TaroCanvas

    2024年01月21日
    浏览(54)
  • 基于网易云音乐API的微信小程序——zwhdlb的音乐平台

    最近在学习小程序的开发的过程中,临时想写一个音乐小程序,看到了网易云 提供了后台api程序,这方便我们直接进行音乐小程序的开发不用再从后端开始开发,网易云音乐平时也经常在用,因此想记录一下学习过程 开发工具:微信开发者工具 界面UI组件库用到的是ColorUI

    2023年04月27日
    浏览(46)
  • 基于uni-app的微信小程序Map事件穿透处理

    业务需要在微信小程序中使用地图组件,上面需要有点位及点位的交互,同时地图上也会有一些悬浮的按钮、弹窗之类的。在微信小程序2.8.x的版本之后,地图这种原生组件是支持同层渲染的,也就是可以通过样式控制层级。在开发者工具中表现正常,但是上了真机后会发现点

    2024年02月11日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包