yunshangxie/tuniao-ui/components/tn-drag/tn-drag.vue

279 lines
6.4 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view
class="tn-drag-class tn-drag"
:style="{
height: wrapHeight + 'rpx'
}"
:list="listData"
:basedata="baseData"
:change:list="wxs.listObserver"
:change:basedata="wxs.baseDataObserver"
>
<!-- #ifdef MP-WEIXIN -->
<view
v-for="(item, index) in listData"
:key="item.id"
class="tn-drag__item"
:style="{
width: 100 / columns + '%',
height: itemHeight + 'rpx'
}"
:data-index="index"
:data-basedata="baseData"
:data-edit="edit"
@longpress="wxs.longPress"
@touchstart="wxs.touchStart"
:catch:touchmove="dragging?wxs.touchMove:''"
:catch:touchend="dragging?wxs.touchEnd:''"
>
<slot :entity="item.data" :fixed="item.fixed" :index="index" :height="itemHeight" :isEdit="edit"></slot>
</view>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<view
v-for="(item, index) in listData"
:key="item.id"
class="tn-drag__item"
:style="{
width: 100 / columns + '%',
height: itemHeight + 'rpx'
}"
@longpress="wxs.longPress"
:data-index="index"
:data-basedata="baseData"
:data-edit="edit"
@touchstart="wxs.touchStart"
@touchmove="wxs.touchMove"
@touchend="wxs.touchEnd"
>
<slot :entity="item.data" :fixed="item.fixed" :index="index" :height="itemHeight" :isEdit="edit"></slot>
</view>
<!-- #endif -->
</view>
</template>
<script src="./index.wxs" lang="wxs" module="wxs"></script>
<script>
export default {
name: 'tn-drag',
props: {
// 数据源
// 如果属性中包含fixed则标识当前数据不允许拖动
list: {
type: Array,
default () {
return []
}
},
// 是否允许拖动编辑
edit: {
type: Boolean,
default: true
},
// 列数
columns: {
type: Number,
default: 3
},
// item元素高度, 单位rpx
itemHeight: {
type: Number,
default: 0
},
// 当前父元素滚动的高度
scrollTop: {
type: Number,
default: 0
}
},
computed: {
wrapHeight() {
return this.rows * this.itemHeight
}
},
data() {
return {
// 未渲染前节点数据
baseData: {},
// 拖动后的数据
dragData: [],
// 行数
rows: 0,
// 渲染数据
listData: [],
// 标记是否正在拖动
dragging: false
}
},
watch: {
list(val) {
this.listData = []
this.$nextTick(() => {
this.init()
})
},
columns(val) {
this.listData = []
this.$nextTick(() => {
this.init()
})
}
},
mounted() {
this.$nextTick(() => {
this.init()
})
},
methods: {
// 初始化
init() {
this.dragging = true
const initDragItem = item => {
const obj = {
...item
}
const fixed = obj?.fixed || false
delete obj["fixed"]
return {
id: this.unique(),
fixed,
data: {
...obj
}
}
}
let i = 0
const listData = (this.list || []).map((item, index) => {
let listItem = initDragItem(item)
// 真实排序
listItem.realKey = i++
// 整体排序
listItem.sortKey = index
listItem.translateX = `${(listItem.sortKey % this.columns) * 100}%`
listItem.translateY = `${Math.floor(listItem.sortKey / this.columns) * 100}%`
return listItem
})
this.rows = Math.ceil(listData.length / this.columns)
this.listData = listData
this.dragData = listData
if (listData.length === 0) return
// console.log(listData);
// 初始化dom元素
this.$nextTick(() => {
this.initRect()
})
},
// 初始化dom元素
initRect() {
const {
windowWidth,
windowHeight
} = uni.getSystemInfoSync()
let baseData = {}
baseData.windowHeight = windowHeight
baseData.realTopSize = 0
baseData.realBottomSize = 0
baseData.columns = this.columns
baseData.rows = this.rows
const query = uni.createSelectorQuery().in(this)
query.select('.tn-drag').boundingClientRect()
query.select('.tn-drag__item').boundingClientRect()
query.exec(res => {
if (!res) {
setTimeout(() => {
this.initRect()
}, 10)
return
}
baseData.itemWidth = res[1].width
baseData.itemHeight = res[1].height
baseData.left = res[0].left
baseData.top = res[0].top + this.scrollTop
this.dragging = false
this.baseData = baseData
})
},
// 触发震动
vibrate() {
uni.vibrateShort()
},
// 滚动到指定的位置
pageScroll(e) {
uni.pageScrollTo({
scrollTop: e.scrollTop,
duration: 0
})
},
// 修改拖动状态
drag(e) {
this.dragging = e.dragging
},
// 拖拽数据发生改变
listDataChange(e) {
this.dragData = e.data
},
// item被点击
itemClick(index) {
const item = this.dragData[index]
this.$emit('click', {
key: item.realKey,
data: item.data
})
},
// 拖拽结束事件
sortEnd(e) {
this.$emit('end', {
data: e.data
})
},
// 排序发生改变事件
change(e) {
this.$emit('change', {
data: e.data
})
},
// 生成元素唯一id
unique(n = 6) {
let id = ''
for (let i = 0; i < n; i++) id += Math.floor(Math.random() * 10)
return 'tn_' + new Date().getTime() + id
}
}
}
</script>
<style lang="scss" scoped>
.tn-drag {
position: relative;
&__item {
position: absolute;
z-index: 2;
top: 0;
left: 0;
}
&__transition {
transition: transform 0.25s !important;
}
&__current {
z-index: 10 !important;
}
&__fixed {
z-index: 1 !important;
}
}
</style>