H5拖拽方法drag在VUE中的应用实例

      网上有关拖拽操作的轮子有很多,但总有一些需求是轮子满足不了的。当使用轮子无法满足自己的需求时,使用H5原生的拖拽方法有以下优势:

  • api丰富,可灵活实现拖拽需求
  • 避免了轮子本身bug修改的不便

      为了让自己深刻理解api,根据需求,我简化实现了一个vue项目中的拖拽实例,也供大家参考。

      需求如下:

     

  • 左侧区域字段不支持排序,但可拖动字段到右侧分层、维度和对比区域
  • 左侧区域字段也可拖动到维度区域已经拖动的第一个字段上,产生层级关系,显示在分层区域中
  • 拖动到维度和对比区域的字段支持互相拖动交换,但维度第一个字段产生层级关系后不能再拖动
  • 分层区域中的字段不支持拖动排序

      代码如下:

    //HTML部分
    <div style="margin-top: 100px;">
        <div class="drag-container">
            <p v-for="item in list"
               draggable="true"
               @dragstart="dragstart($event,item,'list')"
               @dragend="dragend($event,item)"
            >{{item.name}}</p>
        </div>
        <div class="drop-container">
            <p>分层</p>
            <div class="drop-area" v-if="showLayer"
                @drop="drop($event,'layer')"
                @dragenter="dragenter"
                @dragover="dragover"
            >
                <p v-for="(item,index) in layer">
                    <span
                        draggable="true"
                        @dragstart="dragstart($event,item,'layer',index)"
                    >{{item.name}}</span>
                    <b v-if="index!=layer.length-1">-></b>
                </p>
            </div>
            <p>维度</p>
            <div class="drop-area"
                 @drop="drop($event,'dimensions')"
                 @dragover="dragover">
                <span v-for="(item,index) in dimensions"
                      @drop="dropToItem($event,item)"
                      @dragover.prevent
                      draggable="true"
                      @dragstart="dragstart($event,item,'dimensions',index)"
                >{{item.name}}</span>
            </div>
            <p>对比</p>
            <div class="drop-area"
                 @drop="drop($event,'contrasts')"
                 @dragover="dragover">
                <span v-for="(item,index) in contrasts"
                      @dragover.prevent
                      draggable="true"
                      @dragstart="dragstart($event,item,'contrasts',index)"
                >{{item.name}}</span>
            </div>
        </div>
    </div><template>
    <div style="margin-top: 100px;">
        <div class="drag-container">
            <p v-for="item in list"
               draggable="true"
               @dragstart="dragstart($event,item,'list')"
               @dragend="dragend($event,item)"
            >{{item.name}}</p>
        </div>
        <div class="drop-container">
            <p>分层</p>
            <div class="drop-area" v-if="showLayer"
                @drop="drop($event,'layer')"
                @dragenter="dragenter"
                @dragover="dragover"
            >
                <p v-for="(item,index) in layer">
                    <span
                        draggable="true"
                        @dragstart="dragstart($event,item,'layer',index)"
                    >{{item.name}}</span>
                    <b v-if="index!=layer.length-1">-></b>
                </p>
            </div>
            <p>维度</p>
            <div class="drop-area"
                 @drop="drop($event,'dimensions')"
                 @dragover="dragover">
                <span v-for="(item,index) in dimensions"
                      @drop="dropToItem($event,item)"
                      @dragover.prevent
                      draggable="true"
                      @dragstart="dragstart($event,item,'dimensions',index)"
                >{{item.name}}</span>
            </div>
            <p>对比</p>
            <div class="drop-area"
                 @drop="drop($event,'contrasts')"
                 @dragover="dragover">
                <span v-for="(item,index) in contrasts"
                      @dragover.prevent
                      draggable="true"
                      @dragstart="dragstart($event,item,'contrasts',index)"
                >{{item.name}}</span>
            </div>
        </div>
    </div>
    //js部分
    export default {
        name: "drag",
        data(){
            return {
                dragItem:{},//拖动的字段
                dragFrom:'',//拖动从哪开始
                dragIndex:'',//拖动的字段在数组中的索引
                dropIndex:'',//放入地方的字段的索引
                showLayer:false,//是否显示分层
                isDropToItem:false,//是否是拖动到维度字段中进行分层操作
                layer:[],
                dimensions:[],
                contrasts:[],
                list:[
                    {
                        id:1,
                        name:'姓名'
                    },{
                        id:2,
                        name:'性别'
                    },{
                        id:3,
                        name:'年龄'
                    },{
                        id:4,
                        name:'分数'
                    }]
            }
        },
        methods:{
            //拖拽开始
            dragstart(event,item,frm,index){
                console.log('------dragstart------')
                if(this.BrowserType().name == "FF"){
                    // 兼容火狐浏览器,火狐拖拽必须携带数据
                    console.log(event.dataTransfer.setData("imgInfo", event.target.id)); 
                }
                this.dragItem = item;
                this.dragFrom = frm;
                if(!isNaN(index)){
                    this.dragIndex = index;
                }
            },
            //进入拖拽区域,进入时触发一次
            dragenter(event){
                console.log('------dragenter------')
            },
            //进入拖拽区域后多次触发
            dragover(event){
                event.preventDefault();
                var target = event.target;
                this.dropIndex = this.indexFn(target)
                var nodeName = target.nodeName;
                if(nodeName!='SPAN'){
                    this.dropIndex = -1;
                }
            },
            //松开鼠标完成拖拽后触发
            drop(event,target){
                console.log('------drop------')
                var dragFrom = this.dragFrom;
                var dragItem = this.dragItem;
                var dragIndex = this.dragIndex;
                var dropIndex = this.dropIndex;
                if(this.isDropToItem){
                    return;
                }
                if(this.dragFrom == 'layer'){
                    this.layer.splice(dragIndex,1);
                }else if(this.dragFrom == 'dimensions'){
                    this.dimensions.splice(dragIndex,1);
                }else if(this.dragFrom == 'contrasts'){
                    this.contrasts.splice(dragIndex,1);
                }

                if(dragFrom == target && dropIndex>-1){
                    var targetArr = this[target];
                    targetArr.splice(dropIndex,0,dragItem);
                    return;
                }

                if(target == 'layer'){
                    this.layer.push(dragItem);
                }else if(target == 'dimensions'){
                    this.dimensions.push(dragItem);
                }else if(target == 'contrasts'){
                    this.contrasts.push(dragItem);
                }
            },
            //拖动到维度第一个字段时触发
            dropToItem(event,item){
                console.log('------dropToItem------')
                if(this.dragFrom != 'list'){
                    this.isDropToItem = false
                    return;
                }else {
                    this.isDropToItem = true
                }
                if(this.showLayer){
                    this.layer.push(this.dragItem);
                }else{
                    this.showLayer = true;
                    this.layer.push(item);
                    this.layer.push(this.dragItem);
                }
            },
            //拖拽结束后触发,不管是否拖拽成功
            dragend(event,item){
                console.log('------dragend------')
                this.isDropToItem = false
            },
            //判断拖动字段的所以,用于排序
            indexFn(el) {
                var index = 0;
                if (!el || !el.parentNode) {
                    return -1;
                }
                while (el && (el = el.previousElementSibling)) {
                    index++;
                }
                return index;
            },
            //浏览器判断
            BrowserType(){
                var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
                var isOpera = userAgent.indexOf("Opera") > -1; //判断是否Opera浏览器
                var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera; //判断是否IE浏览器
                var isEdge = userAgent.indexOf("Windows NT 6.1; Trident/7.0;") > -1 && !isIE; //判断是否IE的Edge浏览器
                var isFF = userAgent.indexOf("Firefox") > -1; //判断是否Firefox浏览器
                var isSafari = userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") == -1; //判断是否Safari浏览器
                var isChrome = userAgent.indexOf("Chrome") > -1 && userAgent.indexOf("Safari") > -1; //判断Chrome浏览器

                if (isIE)
                {
                    var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
                    reIE.test(userAgent);
                    var fIEVersion = parseFloat(RegExp["$1"]);
                    return {name:"IE",num: fIEVersion};
                }//isIE end

                if (isFF) { return {name:"FF",num: "FF"};}
                if (isOpera) { return {name:"Opera",num: "Opera"};}
                if (isSafari) { return {name:"Safari",num: "Safari"};}
                if (isChrome) { return {name:"Chrome",num: "Chrome"};}
                if (isEdge) { return {name:"Edge",num: "Edge"};}
            }
        }
    }
/* css部分 */
.drag-container{
    width: 100px;height: 500px;float: left; background-color: #BAB5F5;
    p{
        line-height: 40px; text-align: center; cursor: pointer;
    }
}
.drop-container{
    margin-left: 120px; float: left;height: 500px; width: 600px;
    p{
        color: #fff;line-height: 40px;
    }
    .drop-area{
        height: 80px; width: 600px; background-color: #4c72ff;padding: 10px;
        p{
            display: inline-block; margin: 0;
        }
        span{
            display: inline-block;min-width: 50px;line-height: 40px;margin-right: 5px;background-color: #5a3e99;text-align: center;cursor: pointer;
        }
    }
}

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值