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日

相关文章

  • 学习从实践开始之jQuery插件开发 对话框插件开发

    接下来我将为你详细讲解“学习从实践开始之jQuery插件开发 对话框插件开发”的完整攻略。 1. 前置知识 在学习jQuery插件开发之前,你需要掌握以下知识: HTML/CSS 基础知识 JavaScript 基础语法 jQuery 基础语法 2. 对话框插件开发步骤 2.1 需求分析 在开始开发对话框插件之前,需要明确插件的需求,例如插件需要实现哪些功能…

    css 2023年6月10日
    00
  • 微信小程序 小程序制作及动画(animation样式)详解

    微信小程序制作及动画攻略 微信小程序是一种轻量级的应用,由于其小巧、简单易用,已成为颇受欢迎的开发工具。其中,动画效果对于小程序的视觉体验有很大的提升,本攻略主要介绍小程序制作及动画(animation样式)的详解。 小程序制作 1. 新建小程序页面 首先打开微信开发者工具,进入项目页面。 左侧导航栏中找到pages文件夹,右键选择新建页面,设置页面名称、路…

    css 2023年6月10日
    00
  • 深入理解CSS overflow:hidden——溢出,坍塌,清除浮动

    深入理解CSS overflow:hidden——溢出,坍塌,清除浮动 溢出(Overflow) 当元素的内容超出了容器的范围时,我们需要处理这种溢出现象。此时,我们可以使用CSS属性overflow来控制其内容的显示方式。 overflow:hidden 使用overflow:hidden可以隐藏元素的溢出内容,这通常用于父元素中有绝对定位子元素时的处理。…

    css 2023年6月10日
    00
  • css 滤镜效果主要对HTML标记设置滤镜效果

    CSS滤镜是一种CSS属性,它允许你在内容上覆盖一层透明的、可用的效果。 这些效果通常用于图像,但还可以应用于其他元素。 准备 首先,我们需要在HTML中准备一些元素,然后在CSS中添加滤镜。 <div class="container"> <img src="example.jpg" alt=&qu…

    css 2023年6月9日
    00
  • react card slider实现滑动卡片教程示例

    下面是详细的攻略: 1、什么是React Card Slider React Card Slider是一种React组件,它可以让你实现一个类似于滑动卡片的UI效果。用户可以通过鼠标滚轮、键盘或手势来浏览多个卡片,而这些卡片可以自定义大小、颜色和内容,从而适应不同的UI设计。 2、如何安装React Card Slider 要使用React Card Sli…

    css 2023年6月10日
    00
  • css实现左侧固定右侧自适应的布局方式

    下面将介绍如何使用CSS实现左侧固定右侧自适应的布局方式。 使用float属性实现左侧固定 我们可以将左侧容器使用float属性设置为左浮动,同时设置宽度,让其固定在页面的左侧,代码示例如下: <style> .left { width: 200px; height: 500px; float: left; background-color: #…

    css 2023年6月10日
    00
  • 利用js编写响应式侧边栏

    下面是利用JS编写响应式侧边栏的完整攻略: 1. 前言 响应式设计的出现,使得我们可以为不同的屏幕尺寸和设备类型提供不同的布局和用户体验。而一个好的响应式设计在移动设备上需要具备友好的菜单导航,侧边栏便是其中一种常见的解决方案。通过JS编写响应式侧边栏可以实现菜单栏的自适应和开关功能,并能提高用户的交互体验。 2. 整体思路 编写HTML结构 利用CSS设置…

    css 2023年6月10日
    00
  • 微信小程序之侧边栏滑动实现过程解析(附完整源码)

    下面是对该攻略的详细讲解。 一、背景说明 在开发微信小程序的过程中,我们有时候需要实现一个侧边栏滑出的功能,以便用户可以快速地切换页面或使用一些常用功能。本文就是针对这个需求,进行了详细的过程分析和实现。 二、实现过程 下面我们就具体来看如何实现一个侧边栏滑动的功能。 1. 准备工作 首先,我们需要在 app.json 文件中添加一个页面配置,用于展示侧边栏…

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