当前位置:   article > 正文

记录一次vue2项目中拖动div时,div的高度会随着鼠标向上拖动变高_vue-dragable拖拽时页面高度变化

vue-dragable拖拽时页面高度变化

拖动组件:

<template>

    <div

      ref="file-list-win"

      class="file-list-win"

      v-draggable="{limit: true, left: 256, top: 0  }"

      :class="{ min: min == true }"

      style="bottom: 50px"

    >

    <!-- 注意: 如果有拖动的要求,bottom最好不要写在样式文件中,直接写在div的style中,拖动时会清除bottom样式 -->

        <!-- 头部 -->

        <div class="title dragTitle">

            <div>

                <i v-if="getIfAllDone == 1" class="el-icon-success success"></i>

                <div v-else class="loading">

                  <img :src="require('@/assets/images/management/file/loading.png')">

                </div>

            </div>

            <div class="msg">

                <p v-if="getIfAllDone == 1">上传 成功(<span class="success-color">{{ getSuccessCount }}</span>项) 失败(<span class="fail-color">{{ getFailCount }}</span>项)</p>

                <p v-else>正在上传 - 剩余 {{ fileList.length - getDoneCount }} 项</p>

            </div>

            <div class="btns">

                <el-button type="info" circle @click="close()">

                  <i class="el-icon-close"></i>

                </el-button>

                <el-button type="primary" circle v-if="!min" @click="clickSlide()">

                    <i class="el-icon-arrow-up"></i>

                </el-button>

                <el-button type="info" circle v-if="min" @click="clickSlide()">

                    <i class="el-icon-arrow-down"></i>

                </el-button>

            </div>

        </div>

        <div class="content">

            <ul>

                <li

                    v-for="(file, index) in fileList"

                    :key="`item.taskId-${index}`"

                >

                    <div class="bg" v-if="file.status == 'loading' && file.progress > 0" :style="`width: ${file.progress * 100}%`"></div>

                    <div class="bg" v-else style="width: 0"></div>

                    <div class="info">

                        <div class="tb">

                            <template v-if="file.status == 'loading'">

                              <img :src="require('@/assets/images/management/file/file.png')">

                            </template>

                            <template v-else>

                              <img v-if="file.ext =='mp4'" :src="require('@/assets/images/management/file/video.png')"/>

                              <img v-else-if="file.ext =='mp3'" :src="require('@/assets/images/management/file/video.png')"/>

                              <img v-else-if="file.ext =='docx' || file.ext =='doc'" :src="require('@/assets/images/management/file/word.png')"/>

                              <img v-else-if="file.ext =='pptx' || file.ext =='ppt'" :src="require('@/assets/images/management/file/file.png')"/>

                              <img v-else-if="file.ext =='xlsx' || file.ext =='xls'" :src="require('@/assets/images/management/file/excel.png')"/>

                              <img v-else-if="file.ext =='pdf'" :src="require('@/assets/images/management/file/pdf.png')"/>

                              <img v-else :src="require('@/assets/images/management/file/file.png')"/>

                            </template>

                        </div>

                        <div class="msg">

                            <p class="name">{{ file.name }}</p>

                            <p class="other">

                              <span>{{ file.size }}MB</span>

                              <span class="success" v-if="file.status=='success'">上传成功</span>

                              <span class="fail" v-if="file.status=='fail'">上传失败</span>

                            </p>

                        </div>

                    </div>

                </li>

            </ul>

        </div>

    </div>

</template>

<script>

import { mapState } from  'vuex';

export default {

    name: 'FileList',

    components: {},

    props: {

      fileList: {

        type: Array,

        require: true

      }

    },

    data () {

        return {

            min: false,

            height: 0   //存储div本身的高度,展开时计算用到

        };

    },

    computed: {

        // 计算完成的数量

        getDoneCount () {

            return this.fileList.filter(

                (item) => item.status == 'success' || item.status == 'fail'

            ).length;

        },

        // 计算全部导出任务是否完成

        getIfAllDone () {

            let doneCount = this.getDoneCount;

            return doneCount == this.fileList.length ? 1 : 2;

        },

        // 计算成功的数量

        getSuccessCount () {

            return this.fileList.filter(

                (item) => item.status == 'success'

            ).length;

        },

        // 计算失败的数量

        getFailCount () {

            return this.fileList.filter(

                (item) => item.status == 'fail'

            ).length;

        },

    },

    watch: {},

    mounted () {

    },

    methods: {

        // 收起展开

        clickSlide () {

          this.min = !this.min;

          if (!this.min) {

            // 展开

            if (this.$refs['file-list-win'].style.top) {

              // 移动过div

              let top = this.$refs['file-list-win'].style.top;

              let topValue = 0;

              if (top.indexOf('px') > -1) {

                let temp = top.substring(0, top.indexOf('px'));

                topValue = parseInt(temp);

              } else {

                topValue = parseInt(top);

              }

              let h1 = window.innerHeight;

              if (topValue + this.height > h1) {

                // 如果div本身的高度+离顶部的高度 大于 页面的高度,则重新计算div离顶部的高度

                let temp_top = h1 - this.height - 50;

                this.$refs['file-list-win'].style.top = temp_top+'px';

              }

            } else {

              // 未移动过div,不处理

            }

          } else {

            // 收起的时候存下div的高度

            this.height = this.$refs['file-list-win'].offsetHeight;

          }

        },

        // 关闭

        close () {

            if (this.getIfAllDone == 1) {

                this.$emit('closeFileList');

            } else {

                this.$message({

                    type: "warning",

                    message: "有正在进行的任务,请勿关闭!",

                });

            }

        },

    }

};

</script>

<style lang="scss" scoped>

.file-list-win {

    position: fixed;

    right: vw(15);

    // bottom: 50px

    width: vw(400);

    border-radius: 6px;

    z-index:999;

    background: #ffffff;

    box-shadow: rgba(0, 0, 0, 0.1) 0px 3px 5px, rgba(0, 0, 0, 0.06) 0px 6px 10px,

        rgba(0, 0, 0, 0.06) 0px 1px 16px;

    overflow: hidden;

    .title {

        display: flex;

        padding: vh(16) vw(24);

        line-height: vh(24);

        border-bottom: 1px solid #e9e9e9;

        .success {

            color: #66b165;

            font-size: 22px;

            margin-top: 2px;

        }

        .loading {

            width: vw(30);

            height: vw(30);

            img {

              position: relative;

              top: -2px;

              width: 100%;

              height: 100%;

            }

        }

        .msg {

            flex: 1;

            margin-left: vw(10);

            .total {

                color: #909399;

            }

        }

        .btns {

            margin-top: -1px;

            .el-button--medium.is-circle {

                padding: 2px;

            }

            i {

                cursor: pointer;

                font-size: 20px;

            }

        }

    }

    .content {

        max-height: vh(380);

        overflow: auto;

        ul {

            padding: 0;

            li {

                position: relative;

                margin-bottom: vh(10);

                .bg {

                  height: vh(70);

                  background: #F5F5F6;

                  border-bottom: 2px solid #1890FF;

                  z-index: 0;

                }

                .info {

                    position: absolute;

                    left: 0;

                    top: 0;

                    z-index: 1;

                    padding: vh(10) vw(20) vh(10) vw(30);

                    height: vh(50);

                    display: flex;

                    margin-bottom: vh(10);

                    // &:hover {

                    //     background-color: #f5f6f6;

                    // }

                    .tb {

                        width: vw(40);

                        height: vw(40);

                        line-height: vw(40);

                        background: #EAF5FF;

                        border-radius: 6px;

                        text-align: center;

                    }

                    .msg {

                        margin-left: vw(10);

                        flex: 1;

                        .name {

                            width: vw(240);

                            height: vh(30);

                            word-wrap: break-word; /*强制换行*/

                            overflow: hidden; /*超出隐藏*/

                            text-overflow: ellipsis; /*隐藏后添加省略号*/

                            white-space: nowrap; /*强制不换行*/

                            margin: 0;

                        }

                        .other {

                            color: #999999;

                            margin: 0;

                            .success {

                                color: #20A80D;

                                margin-left: vw(10);

                            }

                            .fail {

                                color: red;

                                margin-left: vw(10);

                            }

                        }

                    }

                    .btns {

                        i {

                            cursor: pointer;

                            margin-left: vw(10);

                        }

                        .percent {

                            margin-left: vw(10);

                        }

                    }

                }

            }

        }

    }

    .success-color {

      color: #20A80D;

    }

    .fail-color {

      color: red;

    }

}

.min {

    height: vh(60);

    .content {

        display: none;

    }

}

</style>

拖动指令:

export default {

  install (Vue) {

        // 拖动指令,绑定在div上,

        // 被绑定的div的css样式不要有bottom属性,如果初始化需要用到bottom定位,请直接写在div的style中

        // binding 传值可选 {limit: true, left: 256, top: 0 }

        // limit - 有范围限制,如传入false,可能会拖到父级DOM元素外

        // left - 拖动div离父级DOM左侧最小距离

        // top - 拖动div离父级DOM上侧侧最小距离

        Vue.directive('draggable', {

          // 当被绑定的元素挂载到 DOM 上时...

          bind (el, binding, vnode) {

            const dragTitleEl = el.querySelector('.dragTitle'); // 获取弹窗标题栏元素

            dragTitleEl.style.cssText += ';cursor:move;'

            console.log('binding: ', binding);

            // 添加鼠标按下事件监听

            el.onmousedown = function(e) {

              // 获取鼠标点击位置相对于元素左上角的x,y坐标

              let disX = e.clientX - el.offsetLeft;

              let disY = e.clientY - el.offsetTop;

              // 添加鼠标移动事件监听

              document.onmousemove = function(e) {

                // 计算元素的新位置

                let l = e.clientX - disX;

                let t = e.clientY - disY;

                // 限制拖拽范围

                if (binding.value.limit) {

                  let limit_l = binding.value.left || 0;

                  let limit_t = binding.value.top || 0;

                  if (l < limit_l) {

                    l = limit_l;

                  }

                  if (t < limit_t) {

                    t = limit_t;

                  }

                  if (l > window.innerWidth - el.offsetWidth) {

                    l = window.innerWidth - el.offsetWidth;

                  }

                  if (t > window.innerHeight - el.offsetHeight) {

                    t = window.innerHeight - el.offsetHeight;

                  }

                }

                // 清空之前的样式

                el.style.cssText = "";

                // 设置元素的位置

                el.style.left = l + 'px';

                el.style.top = t + 'px';

              };

              // 添加鼠标抬起事件监听,用于停止拖拽

              document.onmouseup = function(e) {

                document.onmousemove = null;

                document.onmouseup = null;

              };

            };

          }

        })

    }

}

出现错误的原因:

由于最初要求div是定位到右下角,所以使用了bottom属性(且写在样式文件中),在拖动计算过程中,只计算left 和 top属性,所以向上拖动时,由于bottom属性一直存在,div离下边缘的距离不变,但是left属性使div离上边缘的距离变了,就出现了把div高度拖高的问题。

解决方法:

1、bottom直接写在div的style中;

2、拖动过程中使用el.style.cssText = "";  清空样式。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号