vue 拖动改变布局

本文介绍了一种利用Vue和CSS3实现横向布局拖动调整的方法,通过CSS的calc()函数轻松计算并更新左右两侧元素的宽度,简化了传统通过$refs获取和计算宽度的过程。

横向布局 需要拖动框选区域 改变两边元素宽度

<template>
    <div> 
        <div :style="setLeftStyle()" class="view"></div>
        <div id="line" class="line"></div>
        <div :style="setRightStyle()" class="view"></div>
    </div>
</template>

<script>
    data(){
        return{
            width:400,     //默认右边div的宽度
            lastClientX:0 ,  //记录最后一次拖动的横向位置
        }
    },
    mounted(){
        const _this = this;
        this.$nextTick(() => {
            const moveDom = document.getElementById('line');   //拖动元素
            moveDom.onmousedown = function (e) {
              _this.clientStartX = e.clientX;
              document.onmousemove = function (e) {
                _this.moveHandle(e.clientX);
                return false
              };

            document.onmouseup = function () {
               document.onmousemove = null;
               document.onmouseup = null;
               _this.lastClientX = 0;       //清零
            };
          return false
        }
      })
    },
    methods:{
        moveHandle(nowClient) {
            if (this.lastClientX === 0) {   
              // 第一次拖动 记录起始位置  
              this.lastClientX = nowClient;
            } else {
              // 计算拖动的距离 赋值给右边div
              this.width += (this.lastClientX - nowClient);
              // 记录最后一个的拖动位置
              this.lastClientX = nowClient;
            }
       },
       setLeftStyle: function () {
          let wid= this.width+ 7 + 'px';
          //左边div的宽度 等于 100% - (右边div + line的宽度)
          return `width: calc(100% - ${wid});`     
       },
        setRightStyle: function () {
          let wid= this.width+'px';
          return `width:${wid};`
       },
    }
</script>

<style>
    .view{
        height: 100%;
        float: left;
        overflow: auto;
    }
    .line{
        float: left;
        width: 7px;
        height: 100%;
        background: #CEDEF5;
        border-radius: 5px;
        cursor: e-resize;
    }
</style>

之前有看到别的写法 通过$refs获取左右两边的div  再通过计算确定两边宽度再赋值 觉得复杂了 
我这样写 感觉很简单  知道右边宽度  左边的 直接calc() 就可以了  

Vue 中实现拖拽改变元素位置的功能,尤其是用于排序或布局调整的场景,可以通过多种方式完成。以下是几种常见且实用的方法: ### 使用原生 HTML5 拖拽 API Vue 可以直接结合 HTML5 的拖拽 API 来实现基础的拖拽排序功能。通过监听 `dragstart`、`dragover`、`drop` 等事件,可以控制元素的拖拽行为,并在数据层更新排序。 ```html <template> <div> <div v-for="(item, index) in items" :key="item.id" draggable="true" @dragstart="onDragStart(index)" @dragover.prevent @drop="onDrop(index)" > {{ item.name }} </div> </div> </template> <script> export default { data() { return { items: [ { id: 1, name: &#39;Item 1&#39; }, { id: 2, name: &#39;Item 2&#39; }, { id: 3, name: &#39;Item 3&#39; } ], draggedIndex: null }; }, methods: { onDragStart(index) { this.draggedIndex = index; }, onDrop(targetIndex) { const movedItem = this.items.splice(this.draggedIndex, 1)[0]; this.items.splice(targetIndex, 0, movedItem); this.draggedIndex = null; } } }; </script> ``` 此方法适用于简单的拖拽排序场景,但需要手动处理事件逻辑和数据同步 [^1]。 --- ### 使用 vue-draggable-next 插件 对于更复杂的拖拽排序需求,推荐使用 `vue-draggable-next` 插件,它是基于 `Sortable.js` 的 Vue 封装,支持 Vue 3,并提供丰富的功能如动画、嵌套拖拽、边缘自动滚动等。 安装插件: ```bash npm install vue-draggable-next ``` 实现示例: ```html <template> <draggable v-model:list="items" item-key="id"> <div v-for="item in items" :key="item.id"> {{ item.name }} </div> </draggable> </template> <script> import { ref } from &#39;vue&#39;; import draggable from &#39;vue-draggable-next&#39;; export default { components: { draggable }, setup() { const items = ref([ { id: 1, name: &#39;Item 1&#39; }, { id: 2, name: &#39;Item 2&#39; }, { id: 3, name: &#39;Item 3&#39; } ]); return { items }; } }; </script> ``` 该插件简化了拖拽排序的实现,同时支持触摸屏操作和自动滚动,适用于移动端和 PC 端 [^2]。 --- ### 在表格中实现拖拽排序 对于表格组件,尤其是需要支持行拖拽排序、列拖拽排序以及列宽调整的场景,可以结合 `vuedraggable` 和自定义逻辑来实现。 - **行拖拽排序**:使用 `vuedraggable` 对 `<tr>` 或 `<div>` 行元素进行封装。 - **列拖拽排序**:将列转换为可拖拽的结构,确保数据与列顺序保持一致。 - **列宽调整**:通过监听鼠标事件,动态修改列的宽度样式。 ```html <template> <draggable v-model:list="columns" item-key="key"> <table> <thead> <tr> <th v-for="col in columns" :key="col.key">{{ col.label }}</th> </tr> </thead> <tbody> <tr v-for="(row, rowIndex) in data" :key="row.id"> <td v-for="col in columns" :key="col.key"> {{ row[col.key] }} </td> </tr> </tbody> </table> </draggable> </template> ``` 这种实现方式适用于需要高度定制的表格组件,例如支持列宽调整和固定列等高级功能 [^3]。 --- ### 自定义组件封装 如果项目中需要更灵活的拖拽行为,或者希望复用代码,可以考虑封装一个通用的拖拽组件。该组件可以接受 `v-model` 来同步数据,并提供拖拽动画、边缘自动滚动等增强体验。 --- ### 总结 | 方法 | 适用场景 | 优点 | 缺点 | |------|----------|------|------| | 原生 HTML5 拖拽 API | 简单排序需求 | 无需依赖 | 手动处理复杂逻辑 | | vue-draggable-next | 列表/表格拖拽 | 功能丰富,兼容性好 | 需要引入额外库 | | 自定义封装组件 | 高度定制需求 | 灵活性高 | 开发成本较高 | ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值