Vue3实现面板分割

news/2024/10/21 23:06:28/

Vue3实现面板分割

下面是将你提供的 Vue 组件使用 SCSS,并以 Vue 3 的组合式 API 形式的面板分割代码。
1、建立组件相关的文件夹
在这里插入图片描述

2、将下面代码拷贝到index.vue中

<template><div class="g-split" ref="gSplit"><!-- 水平方向 --><div class="horizontal" v-if="showHorizontal"><div class="left-panel position" :style="horizontalLeftPanel"><slot name="left"></slot></div><divclass="horizontal-trigger-panel position":style="horizontaltriggerPanel"ref="horizontalTriggerPanel"><slot name="trigger" v-if="$slots.trigger"></slot><div class="trigger-content-default-wrap" v-else><div class="trigger-content"><i class="trigger-bar" v-for="n in 7" :key="n"></i></div></div></div><div class="right-panel position" :style="horizontalRightPanel"><slot name="right"></slot></div></div><!-- 垂直方向 --><div class="vertical" v-if="showVertical"><div class="top-panel position" :style="verticalTopPanel"><slot name="top"></slot></div><divclass="vertical-trigger-panel position":style="verticaltriggerPanel"ref="verticalTriggerPanel"><slot name="trigger" v-if="$slots.trigger"></slot><div class="trigger-content-default-wrap" v-else><div class="trigger-content"><i class="trigger-bar" v-for="n in 7" :key="n"></i></div></div></div><div class="bottom-panel position" :style="verticalBottomPanel"><slot name="bottom"></slot></div></div></div>
</template><script setup>
import { ref, computed, onMounted } from 'vue';// 注意:页面偏移量单位统一使用百分比计算
const props = defineProps({value: {type: [String, Number],default: 0.5,},mode: {type: String,validator(value) {return ["horizontal", "vertical"].includes(value);},default: "horizontal",},min: {type: [String, Number],default: 0.1,},max: {type: [String, Number],default: 0.9,},
});
import { defineEmits } from 'vue';const emit = defineEmits(['onMoveStart', 'onMoving', 'onMoveEnd']);const gSplit = ref(null);
const horizontalTriggerPanel = ref(null);
const verticalTriggerPanel = ref(null);const left = ref(props.value);
const top = ref(props.value);
const gSplitWidth = ref(0);
const gSplitHeight = ref(0);
const horizontalTriggerPanelWidth = ref(0);
const verticalTriggerPanelHeight = ref(0);const showHorizontal = computed(() => props.mode === "horizontal");
const showVertical = computed(() => props.mode === "vertical");const horizontalLeftPanel = computed(() => ({left: 0,right: (1 - left.value) * 100 + "%",
}));const horizontalRightPanel = computed(() => ({left: (left.value + horizontalTriggerPanelWidth.value / gSplitWidth.value) * 100 + "%",
}));const horizontaltriggerPanel = computed(() => ({left: left.value * 100 + "%",
}));const verticalTopPanel = computed(() => ({top: 0,bottom: (1 - top.value) * 100 + "%",
}));const verticalBottomPanel = computed(() => ({top: (top.value + verticalTriggerPanelHeight.value / gSplitHeight.value) * 100 + "%",
}));const verticaltriggerPanel = computed(() => ({top: top.value * 100 + "%",
}));const initDom = () => {gSplitWidth.value = gSplit.value.clientWidth;gSplitHeight.value = gSplit.value.clientHeight;if (props.mode === "horizontal") {horizontalTriggerPanelWidth.value = horizontalTriggerPanel.value.clientWidth;} else {verticalTriggerPanelHeight.value = verticalTriggerPanel.value.clientHeight;}
};const bindEvent = () => {if (props.mode === "horizontal") {bindHorizontalTriggerPanelEvent();} else {bindVerticalTriggerPanelEvent();}
};const preventSelectedOnMouseMove = (e) => e.preventDefault();const bindHorizontalTriggerPanelEvent = () => {resolveMouseFn("horizontal", horizontalTriggerPanel.value);
};const bindVerticalTriggerPanelEvent = () => {resolveMouseFn("vertical", verticalTriggerPanel.value);
};const resolveMouseFn = (type, element) => {const mousedown = (e) => {document.addEventListener("selectstart", preventSelectedOnMouseMove);emit("onMoveStart", e);const pos = type === "horizontal" ? "left" : "top";const distance = type === "horizontal" ? e.clientX - element.offsetLeft : e.clientY - element.offsetTop;const mousemove = (e) => {emit("onMoving", e);const gSplitSize = type === "horizontal" ? gSplitWidth.value : gSplitHeight.value;const newPos = (type === "horizontal" ? e.clientX - distance : e.clientY - distance) / gSplitSize;if (newPos < props.min) newPos = props.min;if (newPos > 1 - props.min) newPos = 1 - props.min;if (pos === "left") left.value = newPos;else top.value = newPos;};const mouseup = () => {emit("onMoveEnd", e);document.removeEventListener("mousemove", mousemove);document.removeEventListener("mouseup", mouseup);document.removeEventListener("selectstart", preventSelectedOnMouseMove);};document.addEventListener("mousemove", mousemove);document.addEventListener("mouseup", mouseup);};element.addEventListener("mousedown", mousedown);
};onMounted(() => {bindEvent();initDom();
});
</script><style lang="scss">
.g-split {height: 100%;overflow: hidden;.position {position: absolute;}.horizontal {position: relative;height: 100%;.left-panel, .right-panel {height: 100%;}.horizontal-trigger-panel {cursor: col-resize;height: 100%;.trigger-content-default-wrap {background-color: #f8f8f9;height: 100%;position: relative;width: 7px;.trigger-content {position: absolute;top: 50%;transform: translateY(-50%);.trigger-bar {width: 7px;height: 1px;display: block;background: rgba(23, 35, 61, 0.25);margin-top: 3px;}}}}}.vertical {position: relative;height: 100%;.top-panel, .bottom-panel {width: 100%;}.vertical-trigger-panel {width: 100%;.trigger-content-default-wrap {width: 100%;position: relative;height: 7px;cursor: row-resize;background-color: #f8f8f9;.trigger-content {position: absolute;left: 50%;top: 0;transform: translateX(-50%);height: 100%;.trigger-bar {width: 1px;height: 100%;display: inline-block;background: rgba(23, 35, 61, 0.25);margin-left: 3px;vertical-align: top;}}}}}
}
</style>

使用

注册组件

在你的 Vue 项目中,你需要在你的组件或应用程序中注册 GSplitPanel 组件。你可以通过局部注册或全局注册来实现。

局部注册

在你的父组件中导入并注册 GSplitPanel 组件:

<template><div><GSplitPanel mode="horizontal" :value="0.5"><template v-slot:left><div>左侧面板内容</div></template><template v-slot:right><div>右侧面板内容</div></template></GSplitPanel></div>
</template><script setup>
import GSplitPanel from '@/components/Split/index.vue';
</script>
全局注册

如果你希望在整个项目中使用 GSplitPanel 组件,可以在你的主入口文件(如 main.js 或 main.ts)中全局注册:

import { createApp } from 'vue';
import App from './App.vue';
import GSplitPanel from '@/components/Split/index.vue';const app = createApp(App);app.component('GSplitPanel', GSplitPanel);app.mount('#app');

使用组件

在你的项目中,你现在可以使用 标签来使用这个组件。你可以通过 mode 属性来控制是水平分割还是垂直分割,并通过插槽来填充面板的内容。

vue
<GSplitPanel mode="horizontal" :value="0.5"><template v-slot:left><div>左侧面板内容</div></template><template v-slot:right><div>右侧面板内容</div></template>
</GSplitPanel>

http://www.ppmy.cn/news/1538408.html

相关文章

Redis的过期策略和内存淘汰策略

Redis 的过期策略和内存淘汰策略是管理内存和数据有效性的两个重要机制。以下是对这两者的详细介绍&#xff1a; 过期策略 Redis 允许为键设置过期时间&#xff0c;当键的过期时间到达时&#xff0c;Redis 会自动将其删除。过期策略主要包括&#xff1a; 定期删除&#xff1a…

【动物识别系统】Python+卷积神经网络算法+人工智能+深度学习+机器学习+计算机课设项目+Django网页界面

一、介绍 动物识别系统。本项目以Python作为主要编程语言&#xff0c;并基于TensorFlow搭建ResNet50卷积神经网络算法模型&#xff0c;通过收集4种常见的动物图像数据集&#xff08;猫、狗、鸡、马&#xff09;然后进行模型训练&#xff0c;得到一个识别精度较高的模型文件&am…

出海电商新怎样用海外云手机引流?

随着互联网行业的迅猛发展&#xff0c;出海电商、海外社交媒体营销以及游戏产业等领域对技术工具的需求不断增加。在这种趋势下&#xff0c;海外云手机作为一种新型解决方案&#xff0c;正在受到广泛关注。 特别是在出海电商中&#xff0c;平台如亚马逊、速卖通、eBay等通过结合…

Java 微服务网关详解

一、什么是微服务网关&#xff1f; 微服务网关是一个介于客户端与后端服务之间的中间层&#xff0c;它充当了所有服务请求的入口点。客户端无需直接与后端服务进行通信&#xff0c;而是通过网关完成请求的路由、过滤、安全认证等功能。其核心目标是简化客户端的调用逻辑&#…

Flutter平台嵌入器

When you build a Flutter app, it’s not just about the code you write in Dart and the Flutter framework. There’s also a crucial piece called the platform embedders that enable your Flutter app to run on different operating systems like Android, iOS, and s…

mysql查询2张表连接列名一样的情况

people表&#xff1a; person表&#xff1a; SELECT * FROM person LEFT JOIN people on people.idperson.id 查询的结果id(1)和name(1)说明列名重复 SELECT person.id,person.name,people.id as pid,people.name as pname FROM person LEFT JOIN people on people.idperso…

zookeeper kafka集群配置

一.下载安装包 地址&#xff1a;https://download.csdn.net/download/cyw8998/16579797 二.配置文件 zookeeper.properties dataDir/data/kafka/zookeeper_data/zookeeper # the port at which the clients will connect clientPort2181 # disable the per-ip limit on the…

项目计划书,项目经理日常文档,项目管理计划,项目总体实施计划,总体测试计划,总体运维计划,总体开发计划(word原件获取)

项目开发计划包括项目描述、项目组织、成本预算、人力资源估算、设备资源计划、沟通计划、采购计划、风险计划、项目过程定义及项目的进度安排和里程碑、质量计划、数据管理计划、度量和分析计划、监控计划和培训计划等。 软件资料清单列表部分文档&#xff1a; 工作安排任务书…