微信小程序通过 movable-area 做一个与vuedraggable相似的上下拖动排序控件

因为只是做个小案例 我就直接代码写page页面里了 其实很简单 组件稍微改一下就好了
wxss

/* 设置movable-area的宽度 */
.area{
  width: 100%;
}

/* a b c 每条元素的样式 */
movable-view {
  width: calc(100% - 2px);
  background-color: red;
  height: 60rpx;
  line-height: 60rpx;
  color: #FFFFFF;
  text-align: center;
  border: royalblue 1px solid;
}

就是很普通的样式编写

js代码

Page({
  data: {
    //排序的集合数据源
    list: [
      { text: 'a', id: 0 },
      { text: 'b', id: 1 },
      { text: 'c', id: 2 }
    ],
    nodeHeight: 0,  //记录单个节点的高度 px像素单位
    //设置movable-area总高度
    totalHeight: 0
  },
  //第一个要执行的生命周期
  onLoad: function () {
    //调用初始化函数
    this.initialization();
  },
  //将指定元素 在数组中后移一个下标
  moveElementBackward(arr, index) {
    if((index + 1) === arr.length) {
        return arr
    }
    const element = arr[index];
    arr.splice(index, 1);
    arr.splice(index + 1, 0, element);
    return arr;
  },
  //将指定元素 在数组中前移一个下标
  moveIndexForward(arr, index) {
    if(index == 0){
      return arr
    }
    var newArr = Array.from(arr);
    var value1 = newArr[index];
    var value2 = newArr[index - 1];
    newArr[index] = value2;
    newArr[index - 1] = value1;
    return newArr;
  },
  //初始化加载数据
  initialization() {
    //先确认 list是有数据的 如果没有直接 return结束逻辑
    let list = this.data.list
    if(!list.length) {
      return
    }
    const query = wx.createSelectorQuery()
    //获取 node 第一个节点的高度 不然不知道每个节点到底多高
    query.select('.node').boundingClientRect()
    query.exec((doms) => {
      /*
          循环遍历list top是与顶部的距离
          就是  当前下标乘以 当个高度
          例如 一个 40  那么 第二个的位置搞好是 40  而第三个则要在 80 第一个在 0
      */
      list = list.map((item,index) => {
        item.top = (index*doms[0].height)
        return item
      })
      //给总高度 单个节点高度  和  movable-area的高度赋值
      this.setData({
        nodeHeight: doms[0].height,
        totalHeight: (doms[0].height * list.length),
        list: list
      })
    })
  },
  //当用户拖拽完松开手时触发
  handleTouchEnd() {
    //调用initialization 初始化数据
    this.initialization()
  },
  //当用户拖动某块元素时触发
  handleTouchMove: function (event) {
    //获取到当前用拖动的是第几个元素
    const index = event.currentTarget.dataset.index
    //定义一个list 接受tata中的list
    const list = this.data.list
    // 计算出 当前下标应该在的位置  加上  多 三分之二个节点的高度
    const top = ((index * this.data.nodeHeight) + (this.data.nodeHeight * (2/3)))
    // 计算出当前元素应该在的位置  并减去 三分之二个节点的高度
    const bottom = ((index * this.data.nodeHeight) - (this.data.nodeHeight * (2/3)))

    //获取movable-area和movable-view节点
    const query = wx.createSelectorQuery().in(this)
    query.select('.area').boundingClientRect()
    query.selectAll('.node').boundingClientRect()
    query.exec(res => {
      //存储movable-area 元素信息
      const nodeRect = res[0]
      //获取用户当前拖动的元素信息
      const nodeTop = res[1][index]
      //用 node 与屏幕顶部的距离减去 area与屏幕顶部的距离 间距得到  node与area的距离
      const distance = (nodeTop.top - nodeRect.top)
      //用移动距离判断 是否下移了 2/3个节点还要多的距离
      if(distance > top) {
        // 调用 向后移动一个下标的函数
        const newArray = this.moveElementBackward(list, index);
        //调用setData 修改函数 修改 data中的 list 换成我们新处理好的函数
        this.setData({
          list: newArray
        })
        //等待  响应式数据修改并生效后再执行的nextTick
        wx.nextTick(() => {
          //调用初始化函数
          this.initialization();
        })
      }
      //用移动距离判断 是否上移了 2/3个节点还要多的距离
      if(distance < bottom) {
        //调用函数  将 当前下标上一一下  向上调1
        const newArray = this.moveIndexForward(list, index);
        this.setData({
          list: newArray
        })
        //等待  响应式数据修改并生效后再执行的nextTick
        wx.nextTick(() => {
          //调用初始化函数
          this.initialization();
        })
      }
    })
  }
});

我的注释还是写的非常认真的 大家可以好好读一读
然后 wxml 没什么特别的 就是渲染一下list

<movable-area
  class = "area"
  style = "height: {{totalHeight}}px;"
>
  <movable-view
    wx:for="{{list}}"
    wx:key="id"
    data-index="{{index}}"
    y="{{item.top}}"
    direction="all"
    class="node"
    bindtouchmove="handleTouchMove"
    bindtouchend="handleTouchEnd"
  >
    {{item.text}}
  </movable-view>
</movable-area>

在这里插入图片描述
这样 我们就做了一个 可以上下拖动元素排序的小案例了
在这里插入图片描述
效果也是非常不错的

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值