index.vue 3.58 KB
<template>
    <!-- 拖拽交换位置效果 -->
    <transition-group tag="div" class="container">
        <div class="item" v-for="(item, index) in list" :key="index" draggable="true"
            @dragstart="handleDragStart($event, item)" @dragover.prevent="handleDragOver($event, item)"
            @dragenter="handleDragEnter($event, item)" @dragend="handleDragEnd($event, item)">
            <svg-icon v-if="!disabled" icon-class="drag-text" class="el-input__icon input-icon" style="color:#bfbfbf" />
            <span style="margin-right:20px">{{index}}</span>
            <span>{{ item.route }}</span>
        </div>
    </transition-group>
</template>
 
<script>
// draggable 属性规定元素是否可拖动
// dragstart 事件在用户开始拖动元素或选择的文本时触发
// dragover 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
// dragenter - 当被鼠标拖动的对象进入其容器范围内时触发此事件
// dragend - 用户完成元素拖动后触发
export default {
    name: 'Toolbar',
    props: {
        routes: {
            type: Array,
            default: null
        },
        disabled: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            list: [],
            dragging: null
        }
    },
    created() {
        this.list = this.routes
    },
    watch: {
        routes(val) {
            if (val) {
                this.list = val
            }
        }
    },
    methods: {
        handleDragStart(e, item) {
            this.disabled ? '' : this.dragging = item;
        },
        handleDragEnd(e, item) {
            this.disabled ? '' : this.dragging = null
        },
        //首先把div变成可以放置的元素,即重写dragenter/dragover
        // DataTransfer 对象用来保存,通过拖放动作,拖动到浏览器的数据。
        // 如果dropEffect 属性设定为none,则不允许被拖放到目标元素中。
        handleDragOver(e) {
            this.disabled ? '' : e.dataTransfer.dropEffect = 'move'// e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
        },
        handleDragEnter(e, item) {
            if (!this.disabled) {
                e.dataTransfer.effectAllowed = "move"//为需要移动的元素设置dragstart事件
                if (item === this.dragging) {
                    return
                }
                const newItems = [...this.list]
                const src = newItems.indexOf(this.dragging)
                const dst = newItems.indexOf(item)
                // 替换
                newItems.splice(dst, 0, ...newItems.splice(src, 1))
                // 让item的颜色等于新交换的颜色
                this.list = newItems
                this.$emit('drag', newItems)
            }
        }
    }
}
</script>
  
<style lang="scss" scoped>
.container {
    max-width: 350px;
    height: 150px;
    overflow-y: scroll;
    padding: 0;
    border: 1px solid #ccc;

    &::-webkit-scrollbar {
        width: 7px;
        height: 7px;
    }

    &::-webkit-scrollbar-track {
        background-color: #fff;
    }

    &::-webkit-scrollbar-thumb {
        background-color: #ccc;
        border-radius: 20px;
    }

    &::-webkit-scrollbar-thumb:hover {
        background-color: #409eff;
    }

    &::-webkit-scrollbar-track-piece {
        background: #F2F6FC;
    }
}

.item {
    overflow-x: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    /* border-bottom: 1px solid #ccc; */
    cursor: move;
    transition: all linear .3s
}

.item:hover {
    background-color: #c6e2ff;
}
</style>