123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- <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>
|