美文网首页
vue 3 页面上下左右拖拽大小

vue 3 页面上下左右拖拽大小

作者: 执着于98斤的it女 | 来源:发表于2023-07-09 10:29 被阅读0次
    1. split-drag-layout文件夹下 拖拽 index.vue
    <template>
        <div :class="['split-pane', props.isVertical ? 'vertical-pane' : 'level-pane']" :ref="`split${props.isVertical ? 'Vertical' : 'Level'}Ref`">
            <div :class="[props.isVertical ? 'left-pane' : 'top-pane']" ref="topOrLeftRef">
                <slot name="topOrleft" />
            </div>
            <div class="line-box">
                <div :class="['split-line', props.isVertical ? 'vertical-line' : 'level-line']" ref="splitLineRef" @mousedown="onMouseDown($event)">
                    <div class="vertical-line-inner" />
                </div>
                <div v-if="!states.isLeft" alt="图标" class="icon-size icon-left" @click="clickToLeft" />
                <div v-else alt="图标" class="icon-size icon-right" @click="clickToRight" />
            </div>
            <div :class="[props.isVertical ? 'right-pane' : 'bottom-pane']" ref="rightBottomRef">
                <slot name="bottomOrRight" />
            </div>
        </div>
    </template>
    <script lang="ts" setup>
    import { ref, reactive } from 'vue'
    import { getProps } from './index'
    const props = defineProps(getProps())
    const states = reactive({
        isLeft: false,
    })
    // 分割线
    const splitLineRef = ref()
    // 左侧
    const topOrLeftRef = ref()
    // 下侧
    const rightBottomRef = ref()
    // 鼠标拖动事件
    const onMouseDown = e => {
        tableMouse(e, props.isVertical, topOrLeftRef.value, rightBottomRef.value, splitLineRef.value)
    }
    
    const tableMouse = (event, isVertical: Boolean, topOrLeftDom: any, bottomOrRightDom: any, gDom: any) => {
        event = event || window.event
        //设置moveBox捕获所有鼠标按下的事件
        event.target.setCapture && event.target.setCapture()
        //记录鼠标相对于盒子的位移距离
        const offsety = event.clientY
        const offsetx = event.clientX
        const topHOrLeftW = isVertical ? topOrLeftDom.offsetWidth : topOrLeftDom.offsetHeight
        const bottomHOrRightW = isVertical ? bottomOrRightDom.offsetWidth : bottomOrRightDom.offsetHeight
        document.onmousemove = function (event: any) {
            event = event || window.event
            //移动后的鼠标坐标
            const y = event.clientY
            const x = event.clientX
            const num = isVertical ? x - offsetx : y - offsety
            if (isVertical) {
                topOrLeftDom.style.width = `${topHOrLeftW + num < 24 ? 24 : topHOrLeftW + num}px`
                bottomOrRightDom.style.width = `${bottomHOrRightW - num < 24 ? 24 : bottomHOrRightW - num}px`
            } else {
                topOrLeftDom.style.height = `${topHOrLeftW + num}px`
                bottomOrRightDom.style.height = `${bottomHOrRightW - num}px`
            }
        }
        document.onmouseup = function () {
            document.onmousemove = null
            document.onmouseup = null
            //点击 - 移动 - 松开 鼠标松开时,取消对事件的捕获
            gDom.releaseCapture && gDom.releaseCapture()
            states.isLeft = topOrLeftDom.style.width == '24px'
        }
    }
    
    // 点击向左
    const clickToLeft = () => {
        topOrLeftRef.value.style.width = '24px'
        states.isLeft = true
    }
    
    // 点击向右
    const clickToRight = () => {
        topOrLeftRef.value.style.width = '340px'
        states.isLeft = false
    }
    </script>
    <style scoped lang="scss">
    @use './index.scss';
    </style>
    

    2.项目使用方法

    import splitDragLayout from '@/usage/components/split-drag-layout/index'
    <template>
          <splitDragLayout>
                <template #topOrleft>
                   左侧数据
                </template>
                <template #bottomOrRight>
                  右侧数据
                </template>
            </splitDragLayout>
    </template>
    

    3.getProps()方法

    import { PropType } from 'vue'
    
    export function getProps() {
        return {
            /** 高度 */
            height: {
                type: String as PropType<string>,
                default: '100%',
            },
            /** 标题 */
            title: {
                type: String as PropType<string>,
                default: '',
            },
            /** 是否显示 条件栏 */
            isTerm: {
                type: Boolean as PropType<boolean>,
                default: false,
            },
            termPlaceholder: {
                type: String as PropType<string>,
                default: '请输入',
            },
            /** 宽度 */
            width: {
                type: String as PropType<string>,
                default: 'auto',
            },
            /** 边距-上 */
            top: {
                type: String as PropType<string>,
                default: 'var(--ever-gap-s6)',
            },
            /** 边距-右 */
            right: {
                type: String as PropType<string>,
                default: 'var(--ever-gap-s6)',
            },
            /** 边距-下 */
            bottom: {
                type: String as PropType<string>,
                default: 'var(--ever-gap-s6)',
            },
            /** 边距-左 */
            left: {
                type: String as PropType<string>,
                default: 'var(--ever-gap-s6)',
            },
        }
    }
    

    4.index.scss

    .split-pane {
        display: flex;
        height: 100%;
        width: 100%;
    }
    
    .vertical-pane {
        flex-direction: row;
    }
    
    .level-pane {
        flex-direction: column;
    }
    
    .left-pane {
        width: 340px;
        overflow-x: hidden;
    }
    
    .right-pane {
        flex: 1;
    }
    
    .top-pane {
        height: calc(78% - 8px);
    }
    .bottom-pane {
        height: calc(38% - 8px);
    }
    
    .vertical-line {
        width: 1px;
        height: 100%;
        position: relative;
    }
    .vertical-line-inner {
        position: absolute;
        width: 9px;
        background-color: transparent;
        height: 100%;
        cursor: ew-resize;
        left: -4px;
    }
    
    .level-line {
        cursor: ew-resize;
        border-bottom: 1px solid #dce4f2;
        height: 4px;
        background-color: #0000;
    }
    
    .split-line {
        background-color: #dce4f2;
    }
    .split-line:hover {
        background-color: #c2d3f2;
    }
    
    .vertical-line:hover {
        cursor: ew-resize;
    }
    
    // .level-line:hover {
    //     cursor: row-resize;
    // }
    
    .line-box {
        height: 100%;
        position: relative;
    }
    .icon-size {
        width: 28px;
        height: 28px;
        max-width: inherit;
        position: absolute;
        top: 50%;
        left: -14px;
        cursor: pointer;
        z-index: 2;
    }
    .icon-left {
        background: url('@/assets/fold-left.svg') 60%;
    }
    .icon-left:hover {
        background: url('@/assets/fold-left-hover.svg') 60%;
    }
    .icon-right {
        background: url('@/assets/fold-right.svg') 60%;
    }
    
    .icon-right:hover {
        background: url('@/assets/fold-right-hover.svg') 60%;
    }
    

    注:图标文件自己找资源替换哦

    相关文章

      网友评论

          本文标题:vue 3 页面上下左右拖拽大小

          本文链接:https://www.haomeiwen.com/subject/fbcsudtx.html