vue3 可拖动的左右面板分割组件实现

针对“vue3 可拖动的左右面板分割组件实现”的话题,我将为你提供详细的攻略,包含以下内容:

  1. 确定组件需求和功能
  2. 搭建基本的组件结构和布局
  3. 实现拖动效果
  4. 处理拖动边缘限制和动态宽度变化
  5. 实现完整功能

下面我们就来一步一步地讲解每个步骤,供你参考。

1. 确定组件需求和功能

我们的目标是创建一个可拖动的左右面板分割组件,使得用户可以自由拖动左右两个面板的宽度,以实现多种效果。具体功能如下:

  • 左右两个面板的宽度可以自由拖动调整,满足不同的排布需求;
  • 拖动过程中,两个面板的宽度比例可以自适应调整,并始终保持在一个合理的范围内;
  • 当拖动到最左边或最右边时,左或右面板不能再继续往左或右移动。

2. 搭建基本的组件结构和布局

在Vue3中,通常我们会使用单文件组件(SFC)来开发,因此我们需要创建一个名为SplitPane.vue的组件文件,并在里面添加模板,脚本和样式三个部分。

现在我们来定义组件模板,实现基本的布局效果:

<template>
  <div class="split-pane">
    <div class="split-pane__left" :style="{ width: leftWidth + '%'}"></div>
    <div class="split-pane__dragbar"></div>
    <div class="split-pane__right" :style="{ width: rightWidth + '%'}"></div>
  </div>
</template>

其中,我们定义了三个容器元素:split-pane、split-pane__left和split-pane__right,分别对应整个组件,左面板和右面板。我们还定义了一个分割条元素split-pane__dragbar,用于拖动调整面板宽度。

3. 实现拖动效果

现在我们开始实现拖动效果。我们可以在分割条上绑定一个mousedown事件,并在拖动条上添加一个“可拖动”类(dragging),以供后面调整样式用。同时,我们还需要绑定整个文档的mousemove和mouseup事件,以处理当鼠标移动或者松开时的拖动效果。

下面是代码示例:

<template>
  <div class="split-pane">
    <div class="split-pane__left" :style="{ width: leftWidth + '%'}"></div>
    <div class="split-pane__dragbar" @mousedown="handleMouseDown"></div>
    <div class="split-pane__right" :style="{ width: rightWidth + '%'}"></div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dragging: false, // 是否在拖动中
      leftWidth: 50, // 左面板的宽度
      rightWidth: 50 // 右面板的宽度
    };
  },
  methods: {
    handleMouseDown() {
      // 绑定mousemove、mouseup事件
      document.addEventListener('mousemove', this.handleMouseMove);
      document.addEventListener('mouseup', this.handleMouseUp);
      // 添加拖动样式
      this.dragging = true;
      document.body.classList.add('dragging');
    },
    handleMouseMove(event) {
      if (this.dragging) {
        // 计算拖动的距离
        const dx = event.pageX - this.$refs.dragbar.offsetLeft;
        const totalWidth = this.$el.clientWidth;
        // 计算左右两个面板的宽度
        const leftWidth = ((this.leftWidth / totalWidth) * totalWidth + dx) / totalWidth * 100;
        const rightWidth = ((this.rightWidth / totalWidth) * totalWidth - dx) / totalWidth * 100;
        // 更新状态
        this.leftWidth = leftWidth > 0 ? leftWidth : 0;
        this.rightWidth = rightWidth > 0 ? rightWidth : 0;
      }
    },
    handleMouseUp() {
      // 解除事件绑定和拖动样式
      document.removeEventListener('mousemove', this.handleMouseMove);
      document.removeEventListener('mouseup', this.handleMouseUp);
      this.dragging = false;
      document.body.classList.remove('dragging');
    }
  }
};
</script>

<style scoped>
.split-pane {
  display: flex;
  height: 500px;
  overflow: hidden;
  position: relative;
}

.split-pane__left,
.split-pane__right {
  height: 100%;
  position: absolute;
  top: 0;
}

.split-pane__left {
  left: 0;
  background-color: #f0f0f0;
}

.split-pane__right {
  right: 0;
  background-color: #fff;
}

.split-pane__dragbar {
  height: 100%;
  width: 10px;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  cursor: ew-resize;
}

.dragging {
  user-select: none;
  -moz-user-select: none;
  -webkit-user-select: none;
}
</style>

4. 处理拖动边缘限制和动态宽度变化

在第三步中,我们已经成功地实现了基本的拖动效果。但是,在实际操作中我们会发现,在拖动到左边沿或右边沿时,左侧或右侧的面板不会再继续移动,这是我们需要进行进一步处理的地方。

我们可以在handleMouseMove方法中添加如下代码,来限制拖动的最小和最大宽度:

const minLeftWidth = 0;
const maxRightWidth = 100;
const percentWidth = totalWidth / 100; // 计算总宽度的百分比

// 计算限制后的宽度
const left = leftWidth > minLeftWidth ? leftWidth : minLeftWidth;
const right = rightWidth > 0 ? (rightWidth < maxRightWidth ? rightWidth : maxRightWidth) : 0;

// 计算拖动后左、右面板的宽度,并进行相应的百分比转换
this.leftWidth = left / percentWidth;
this.rightWidth = right / percentWidth;

另外,我们可能还会发现一个问题:当拖动后,两个面板的宽度比例可能不会保持不变,这可能会导致排版效果不佳。解决这个问题的办法是在组件初始化的时候,根据初始比例计算出左右面板的宽度,随着拖动变化也可以根据新的比例计算出左右面板的宽度来进行动态更新。

5. 实现完整功能

现在我们已经实现了拖动效果并限制了左右面板的拖动边界,但我们的组件是静态的,无法响应外部的变化。因此,我们需要在SplitPane组件中添加一个props来允许外部传入初始的左右面板宽度比例,从而能够动态更新组件的状态。

同时,我们可以添加事件回调并在拖动状态发生改变时进行触发:

export default {
  props: {
    initLeftWidth: {
      type: Number,
      default: 50
    },
    initRightWidth: {
      type: Number,
      default: 50
    }
  },
  data() {
    return {
      dragging: false,
      leftWidth: this.initLeftWidth,
      rightWidth: this.initRightWidth
    };
  },
  mounted() {
    const totalWidth = this.$el.clientWidth;
    const percentWidth = totalWidth / 100;
    this.leftWidth = this.initLeftWidth / percentWidth;
    this.rightWidth = this.initRightWidth / percentWidth;
  },
  methods: {
    handleMouseMove(event) {
      // ...
      if (this.dragging) {
        // 计算拖动的距离
        const dx = event.pageX - this.$refs.dragbar.offsetLeft;
        const totalWidth = this.$el.clientWidth;
        // 计算左右两个面板的宽度
        const leftWidth = ((this.leftWidth / percentWidth) * totalWidth + dx) / totalWidth * 100;
        const rightWidth = ((this.rightWidth / percentWidth) * totalWidth - dx) / totalWidth * 100;
        // 计算限制后的宽度
        const minLeftWidth = 0;
        const maxRightWidth = 100;
        const left = leftWidth > minLeftWidth ? leftWidth : minLeftWidth;
        const right = rightWidth > 0 ? (rightWidth < maxRightWidth ? rightWidth : maxRightWidth) : 0;
        // 计算拖动后左、右面板的宽度,并进行相应的百分比转换
        this.leftWidth = left / percentWidth;
        this.rightWidth = right / percentWidth;
        // 触发事件回调
        this.$emit('dragging', this.leftWidth, this.rightWidth);
      }
    },
    handleMouseUp() {
      // ...
      this.$emit('draggend', this.leftWidth, this.rightWidth);
    }
  }
};

这样,我们就成功地实现了一个可拖动的左右面板分割组件,并且可以响应外部状态变化。接下来,我们可以在父组件中使用这个组件,并进行相应的事件调用。

下面提供一个示例代码供你参考:

<template>
  <div>
    <SplitPane ref="splitPane" :init-left-width="30" :init-right-width="70" @dragging="handleDragging" @dragend="handleDragEnd" />
  </div>
</template>

<script>
import SplitPane from './SplitPane.vue';

export default {
  components: {
    SplitPane
  },
  methods: {
    handleDragging(leftWidth, rightWidth) {
      console.log('正在拖动,当前状态:', leftWidth, rightWidth);
    },
    handleDragEnd(leftWidth, rightWidth) {
      console.log('拖动结束,最终状态:', leftWidth, rightWidth);
    }
  }
};
</script>

这里我们可以看到,我们实例化了一个SplitPane组件,并对其进行了一些props传递和事件监听。当我们拖动时,就可以看到SplitPane组件会动态地更新状态,并打印出事件回调的内容。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue3 可拖动的左右面板分割组件实现 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • JavaScript编写一个简易购物车功能

    实现一个简易购物车功能,需要以下步骤: 第一步:创建HTML页面 创建一个HTML页面,用于展示商品列表、购物车内容和总价。 <!DOCTYPE html> <html> <head> <title>购物车</title> <meta charset="utf-8">…

    css 2023年6月10日
    00
  • 使用CSS媒体查询和JavaScript判断浏览器设备类型的好方法

    下面我将详细讲解如何使用CSS媒体查询和JavaScript判断浏览器设备类型,并提供两个示例说明。 使用CSS媒体查询 CSS媒体查询可以在CSS中给不同的设备类型应用不同的样式。通过媒体查询,我们可以根据浏览器窗口的大小、分辨率、设备类型等特性,来为不同的设备应用不同的样式。 媒体查询是通过@media语句来定义的,例如: /* 移动设备样式 */ @m…

    css 2023年6月10日
    00
  • 使用css样式设计一个简单的html登陆界面的实现

    使用CSS样式可以轻松地设计一个简单的HTML登录界面。下面是一个完整的攻略,包含实现步骤和两个示例说明。 创建HTML文件和CSS文件 首先,创建一个HTML文件(例如“login.html”)和一个CSS文件(例如“login.css”)。在HTML文件的部分导入CSS文件: <head> <link rel="stylesh…

    css 2023年6月9日
    00
  • 原生javascript+css3编写的3D魔方动画旋扭特效

    下面我将详细讲解“原生javascript+css3编写的3D魔方动画旋扭特效”的完整攻略,希望对您有所帮助。 简介 3D魔方动画旋扭特效是一种非常炫酷的页面特效,可以提高网站的可视性和用户体验。该特效基于原生Javascript和CSS3技术,可以实现3D模型的旋转、拖拽、还原等动态效果。 实现步骤 下面是实现该特效的完整步骤: 第一步:创建3D模型 首先…

    css 2023年6月10日
    00
  • CSS教程之div垂直居中的多种方法

    下面是关于CSS中div垂直居中的多种方法的完整攻略。 方法一:使用flex布局 在CSS3中,flex布局提供了一种简单且有效的垂直居中方法。可以通过以下步骤实现: 将父元素的display属性设置为flex 将父元素的justify-content和align-items属性都设置为center,即水平居中和垂直居中。 示例如下: <style&g…

    css 2023年6月10日
    00
  • 表格边框的css语法

    下面是关于表格边框的css语法的完整攻略: 语法 在CSS中,我们可以使用 border 属性来设置表格边框的样式。border 属性由三个子属性组成,分别是 border-width、 border-style和 border-color。下面是 border 属性的完整语法: border: border-width border-style borde…

    css 2023年6月9日
    00
  • Bootstrap CSS布局之表格

    下面就是Bootstrap CSS布局之表格的完整攻略。 Bootstrap CSS布局之表格 Bootstrap是一个流行的CSS框架, 提供了大量预设的CSS样式和JavaScript插件。其中,表格是Bootstrap提供的一种常用的布局方式。Bootstrap表格具有响应式设计,能够适应各种大小的屏幕,如手机和平板电脑。 一个简单的表格 下面是一个简…

    css 2023年6月10日
    00
  • win7系统设置网页背景颜色如绿色和豆绿色来保护眼睛

    请你先了解一下markdown的基本语法,以便于理解本文本中的标记和格式。首先,我们需要了解如何更改网页的背景颜色。在HTML中,可以通过设置CSS样式来实现此功能。因此,我们需要在网页head标签内添加一个style标签,并在其中设置相应的颜色值。以下是一个例子。 步骤一:打开Win7系统的控制面板 点击Win7系统的“开始”按钮,在“开始”菜单中选择“控…

    css 2023年6月9日
    00
合作推广
合作推广
分享本页
返回顶部