uniapp编译微信小程序拖动排序

本文若对你有用,给个免费 Star 和关注,持续输出前端各种稀奇古怪的问题

所实现的效果如图

拖动.gif

代码如下,注释齐全

  • 本段代码用到scss
<template>
  <!-- 拖动 -->
  <view class="edit-box" :style="{top:`100px`}">
    <view class='zhuti'>
      <scroll-view :scroll-y='pageInfo.scrollY' class='product-section'>
        <block v-for="(item,index) in optionLists" :key="index">
          <!-- 此处 :key='index' 不能改,只支持拖动排序,不支持修改 -->
          <view class='row list-row' :class='{"ready-place":pageInfo.readyPlaceIndex === index}'
            :style='"height: "+pageInfo.rowHeight+"px;"'>
            <view class='col1 content'>
              <text>{{item.name}}</text>
            </view>
            <view class="col3">
              <text class="iconfont icon-tuodong" 
                :data-index='index' @touchstart='dragStart'
                @touchmove='dragMove' @touchend='dragEnd'
              ></text>
            </view>
          </view>
        </block>
      </scroll-view>
      <movable-area class="movable-area"
        :style='"display:"+movableViewInfo.showClass+"; height:"+pageInfo.scrollHeight+"%"'>
        <movable-view class='row list-row movable-row' :out-of-bounds='true' damping='999'
          :style='"height:"+pageInfo.rowHeight+"px;"' direction="vertical" :y="movableViewInfo.y"
        >
          <view class='col1 content'>{{movableViewInfo.data}}</view>
          <view class="col3">
            <text class="iconfont icon-tuodong"></text>
          </view>
        </movable-view>
      </movable-area>
    </view>
  </view>
</template>

<script>
  export default {
    name: 'dragEdit',
    data() {
        return {
        // 拖动框内数据,配置
        movableViewInfo: {
          y: 0,
          showClass: 'none',  
          data: {}
        },
        optionLists: [
          { name: '苹果', code:'apple' },
          { name: '橘子', code:'orange' },
          { name: '香蕉', code:'banana' },
          { name: '油桃', code:'nectarine' },
          { name: '桃子', code:'peach' },
          { name: '蟠桃', code:'peento' },
          { name: '葡萄', code:'grape' },
          { name: '椰子', code:'coco' },
          { name: '草莓', code:'strawberry' },
          { name: '牛油果', code:'avocado' },
          { name: '枇杷', code:'loquat' },
          { name: '梨', code:'pear' },
          { name: '杏子', code:'apricot' },
          { name: '樱桃', code:'cherry' },
          { name: '甜瓜', code:'cantaloupe' },
          { name: '西瓜', code:'watermelon' },
          { name: '蓝莓', code:'blueberry' },
          { name: '猕猴桃', code:'kiwifruit' },
          { name: '菠萝', code:'pineapple' },
          { name: '柿子', code:'persimmon' },
          { name: '无花果', code:'fig' },
        ],
        pageInfo: {
          scrollY: true,        // 当为true时拖动单条,整个大盒子不会滚动
          rowHeight: 37,      // 单条行高
          scrollHeight: 100,      // 拖动时行高,百分比
          startIndex: null,     // 当前拖动第几条
          startY: 0,            // 定位拖动时的位置,需要减去上方空白部分
          readyPlaceIndex: null,    // 拖动预放置位置,拖动时有阴影的部分
          selectedIndex: null,  // 放置的位置
        }
      }
    },
    methods:{
      // 拖拽开始(按下)
      dragStart(event) {
        var startIndex = event.currentTarget.dataset.index
        // 初始化页面数据
        var pageInfo = this.pageInfo
        // 减去距离页面顶部的距离
        pageInfo.startY = event.touches[0].clientY-162
        pageInfo.readyPlaceIndex = startIndex
        pageInfo.selectedIndex = startIndex
        pageInfo.scrollY = false
        pageInfo.startIndex = startIndex
        
        // console.log('startIndex', pageInfo.readyPlaceIndex)
        this.movableViewInfo.y = pageInfo.startY - (pageInfo.rowHeight / 2)
        // 初始化拖动控件数据
        var movableViewInfo = this.movableViewInfo
        movableViewInfo.data = this.optionLists[startIndex].name
        movableViewInfo.showClass = "inline"
      
      
        this.movableViewInfo = movableViewInfo,
        this.pageInfo = pageInfo
      },
      // 拖拽移动(按住不松)
      dragMove(event) {
        var optionLists = this.optionLists
        var pageInfo = this.pageInfo
        // 计算拖拽距离
        var movableViewInfo = this.movableViewInfo
        var movedDistance = event.touches[0].clientY-162 - pageInfo.startY
        movableViewInfo.y = pageInfo.startY - (pageInfo.rowHeight / 2) + movedDistance
        // console.log('移动的距离为', movedDistance, movableViewInfo.y)
      
        // 修改预计放置位置
        var movedIndex = parseInt(movedDistance / pageInfo.rowHeight)
        var readyPlaceIndex = pageInfo.startIndex + movedIndex
        if (readyPlaceIndex < 0) {
          readyPlaceIndex = 0
        } else if (readyPlaceIndex >= optionLists.length) {
          readyPlaceIndex = optionLists.length - 1
        }
      
        if (readyPlaceIndex != pageInfo.selectedIndex) {
          var selectedData = optionLists[pageInfo.selectedIndex]
      
          optionLists.splice(pageInfo.selectedIndex, 1)
          optionLists.splice(readyPlaceIndex, 0, selectedData)
          // console.log('======optionLists', optionLists)
          pageInfo.selectedIndex = readyPlaceIndex
        }
        // 移动movableView
        pageInfo.readyPlaceIndex = readyPlaceIndex
        // console.log('移动到了索引', readyPlaceIndex, '选项为', optionLists[readyPlaceIndex])
      
      
        this.movableViewInfo = movableViewInfo
        this.optionLists = optionLists
        this.pageInfo = pageInfo
      },
      // 拖拽结束(松手)
      dragEnd(event) {
        /**
         * this.optionLists 在 dragMove 函数已经出现,
         * 但是在 dragMove 函数会多次触发,
         * 发送数据,及观察数据,在此处即可
         */
        let arr = []
        this.optionLists.forEach(item=>{
          arr.push(item.name)
        })
        console.log('optionLists',arr)
        
        // 重置页面数据
        var pageInfo = this.pageInfo
        // console.log('=====this.pageInfo before', this.pageInfo)
        // console.log('event', event)
        pageInfo.readyPlaceIndex = null
        pageInfo.startY = null
        pageInfo.selectedIndex = null
        pageInfo.startIndex = null
        pageInfo.scrollY = true
        // 隐藏movableView
        var movableViewInfo = this.movableViewInfo
        movableViewInfo.showClass = 'none'
        this.movableViewInfo = movableViewInfo
        this.pageInfo = pageInfo
        // console.log('=====this.movableViewInfo', this.movableViewInfo)
        // console.log('=====this.pageInfo', this.pageInfo)
      },
    },
  }
</script>

<style lang="scss" scoped>
  @import '/static/css/iconfont.css';
  /* 模块编辑 */
  .edit-box { width: 100%; position: absolute;
    bottom: 0; left: 0; overflow: hidden; margin-bottom: 20rpx;
  }
  .marginL6 { margin-left: 12rpx; }
  .product-section { height:100%; }
  .zhuti { width: 100%; position: absolute; top: 52px;
    bottom: 0; left: 0; overflow: scroll; }
  .row { height: 47px; width: 100%; display: flex; justify-content: space-between; align-items: center; }
  .title-row { border-bottom: 1px solid #888888; color: #888888; }
  .list-row { padding: 4px 24rpx; background-color: white; box-sizing: border-box;}
  .movable-area { position: absolute; top: 0; left: 0; z-index: 10; width: 100%; }
  .movable-row { box-shadow: #D9D9D9 0 0 20px; }
  .col1 { width: 90%; }
  .col3 { width: 6%; color: #3C63EB; }
  .ready-place { background: rgba(238, 240, 254, 0.6); }
  .content { font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border: 1rpx solid #3C63EB; color:#3C63EB; box-sizing: border-box; height: 58rpx; padding: 8rpx 0 8rpx 32rpx; border-radius: 4rpx; }
</style>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容