用vue3+elementplus做的一个滚动菜单栏的组件

news2024/10/7 15:20:36

目录

  • 起因
  • 概览
  • 设计及解决思路
    • 1.滚动条竖起来
    • 2.绑定菜单
    • 3.吸附
    • 优化
  • 组件全部代码

起因

在elementplus中看到了滚动条绑定了slider,但是这个感觉很不实用,在底部,而且横向滚动,最常见的应该是那种固定在左上角的带着菜单的滚动条,于是我就想要不做一个小demo,方便以后使用
在这里插入图片描述

概览

样式如下:(背景是我父组件的背景色
在这里插入图片描述

设计及解决思路

1.滚动条竖起来

首先不能用横着的滚动条,一开始我是想用transform来旋转的,后来我发现这玩意是靠鼠标位置来决定数值大小的,所以就算transform还是得横着拖,所以采用竖着的slider;
slider是竖起来了,但是如何和滚动条绑定呢,elementplus里面使用的是el-scrollbar,但是如果这是一个信息页,你不可能把它放在一个el-scrollbar中,那么只有用当前位置/window的高度来决定slider的数值,实现方法及算法如下:

<el-slider
            v-model="heighRatio"
            :show-tooltip="false"
            vertical
            :height="scrollBarHeight"
            @input="scrollInput"
          />

const heighRatio = ref(100);
function scrollInput() {
  window.scrollTo(0, ((100 - heighRatio.value) * document.body.clientHeight) / 100);
}

function handleScroll() {
  heighRatio.value =
    100 - (document.documentElement.scrollTop / document.body.clientHeight) * 100;
}

onMounted(() => {
  // 给window绑定滚动事件
  window.addEventListener("scroll", handleScroll);	
});

2.绑定菜单

假设它的信息页的内容是分title和content的,我们就可以用title形成菜单然后点击进行跳转,给每个content的title标记上id,就可以用#进行页内跳转

	<div class="contentTitle">
           <a :href="'#' + item.title" class="contentItem" v-for="item in arrayData">
              {{ item.title }}
           </a>
    </div>
    <!-- 内容部分 -->
    <div class="content" id="content">
      <div class="part" v-for="item in arrayData">
        <h2 :id="item.title">{{ item.title }}</h2>
        <p>{{ item.content }}</p>
      </div>
    </div>

3.吸附

这个菜单滚动条既然能够点击拖动,那么就必须一直在视口内,所以要通过吸附让它一直显现,而elementplus刚好具有这种组件Affix,直接采用即可。

优化

顺便加了一个回到顶部的按钮,只要添上内容这个信息页就比较完整了

组件全部代码

<template>
  <el-container>
    <!-- 自定义滚动条 -->
    <div class="scrollMenu">
      <el-affix :offset="120">
        <div style="display: flex">
          <el-slider
            v-model="heighRatio"
            :show-tooltip="false"
            vertical
            :height="scrollBarHeight"
            @input="scrollInput"
          />
          <div class="contentTitle">
            <a :href="'#' + item.title" class="contentItem" v-for="item in arrayData">{{
              item.title
            }}</a>
          </div>
        </div>
      </el-affix>
    </div>

    <!-- 内容部分 -->
    <div class="content" id="content">
      <div class="part" v-for="item in arrayData">
        <h2 :id="item.title">{{ item.title }}</h2>
        <p>{{ item.content }}</p>
      </div>
    </div>

    <!-- 返回顶部 -->
    <el-backtop :bottom="100">
      <div
        style="
          height: 100%;
          width: 100px;
          background-color: var(--el-bg-color-overlay);
          box-shadow: var(--el-box-shadow-lighter);
          border-radius: 50%;
          text-align: center;
          line-height: 40px;
          color: #1989fa;
        "
      >
        <el-icon><ArrowUp /></el-icon>
      </div>
    </el-backtop>
  </el-container>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { ArrowUp } from "@element-plus/icons-vue";
const heighRatio = ref(100);
const scrollBarHeight = ref("200px");
const arrayData = ref([
  { title: "标题111", content: "111111111111111111" },
  { title: "标题2222222222222222222222222", content: "111111111111111111" },
  { title: "标题333", content: "111111111111111111" },
  { title: "标题444", content: "111111111111111111" },
  { title: "标题555", content: "111111111111111111" },
  { title: "标题666", content: "111111111111111111" },
  { title: "标题777", content: "111111111111111111" },
  { title: "标题888", content: "111111111111111111" },
]);

function scrollInput() {
  window.scrollTo(0, ((100 - heighRatio.value) * document.body.clientHeight) / 100);
}

function handleScroll() {
  heighRatio.value =
    100 - (document.documentElement.scrollTop / document.body.clientHeight) * 100;
}

onMounted(() => {
  window.addEventListener("scroll", handleScroll);
  scrollBarHeight.value = arrayData.value.length * 30 + "px";
});
</script>
<style>
.scrollMenu{
    margin-right: 50px;
}
.contentItem {
  text-align: left;
  height: 30px;
  width: 100px;
  text-decoration: none;
  display: block;
  line-height: 30px;;
  color: #409eff;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  -o-text-overflow: ellipsis;
  border-top: 1px solid #409eff;
}
.contentItem:last-child{
    border-bottom: 1px solid #409eff;
}
.content {
  padding: 50px 200px 50px 20px;
  flex: 1;
}
.part {
  height: 800px;
  background: #ccc;
}
</style>


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/704100.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL总结(索引,Explain,MVCC和隔离级别,锁)

文章目录 一、索引1.索引构成2.如何查找3.最左匹配原则4.覆盖索引5.减少冗余索引和重复索引1.冗余索引2.重复索引 6.索引适用情况和注意事项1.适用情况2.注意事项 二、Explain执行计划1.Explain语句 三、隔离级别与MVCC1.事前准备2.四个事务并发的问题1.脏写2.脏读3.不可重复读…

(有10个维度为(256,128,130)的tensor,计算10个tensor两两之间的相似性以及差异性,并将相似性和差异性可视化。

有10个维度为&#xff08;256,128,130&#xff09;的tensor&#xff0c;计算10个tensor两两之间的相似性以及差异性&#xff0c;并将相似性和差异性可视化。 问题描述解决办法 问题描述 有10个维度为&#xff08;256,128,130&#xff09;的tensor&#xff0c;计算10个tensor两…

Java基础复习第二天

目录 一、字符串 二、不可变的好处 三、String&#xff0c; StringBuffer and StringBuilder的区别 四、字符串池 五、新字符串&#xff08;“abc”&#xff09; 一、字符串 String 被声明为 final&#xff0c;因此它不可被继承。&#xff08;Integer 等包装类也不能被继承…

前端-基础选择器

从今天开始学习下前端的知识-查漏补缺&#xff0c;仅为自己学习记录使用 基础选择器 标签选择器类选择器id 选择器通配符选择器 标签选择器 标签名 {属性名&#xff1a;属性值; }<style>p {color: red;} </style><p>你好&#xff0c;世界</p>类选择…

Unity URP 获取Camera Stack

URP 获取Camera Stack 1.using UnityEngine.Rendering.Universal; 2.Camera.main.GetUniversalAdditionalCameraData().cameraStack

【日志加载 log4j】

日志 笔记记录 1. 日志介绍2. 日志体系结构3.Log4j开发流程4.Log4j组成4.1 Loggers 记录器4.2 Appenders 输出源4.3 Layouts 布局5. 配置文件 log4j.properties 1. 日志介绍 2. 日志体系结构 3.Log4j开发流程 1.引入依赖<dependency><groupId>log4j</groupId>…

爬虫正常用哪种代理比较好?

在进行网络爬虫时&#xff0c;使用代理可以带来许多好处&#xff0c;包括提高请求的可靠性、防止IP封锁、实现匿名浏览等。以下是一些常见的代理类型&#xff0c;你可以根据需要选择最适合的&#xff1a; 免费代理&#xff1a;免费代理可能数量众多&#xff0c;但质量和稳定性参…

Python获取某品牌加盟数据采集实现可视化数据分析

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 开发环境 : python 3.8 运行代码 pycharm 2022.3 辅助敲代码 jupyter 数据分析使用软件 模块使用 &#xff1a; requests 数据请求模块 需要安装 parsel 数据解析模块 csv pandas pyecharts 第三方模块安装&#xf…

基于Java开发的企业人力资源管理系统(ehr系统)

一、项目介绍 一款全源码可二开&#xff0c;可基于云部署、私有部署的企业级数字化人力资源管理系统&#xff0c;涵盖了招聘、人事、考勤、绩效、社保、酬薪六大模块&#xff0c;解决了从人事招聘到酬薪计算的全周期人力资源管理&#xff0c;符合当下大中小型企业组织架构管理…

BOLD信号的生理建模及其对有效连接的影响

导读 本文提供了BOLD信号生理过程的总体概述(即生成生物物理模型)&#xff0c;包括它们在生理信息动态因果模型(P-DCM)框架下的时间过程特征。BOLD信号主要由顺磁性脱氧血红蛋白的变化决定&#xff0c;而顺磁性脱氧血红蛋白的变化是氧代谢、脑血流量和脑血容量变化共同作用的结…

测试工程师首chatGPT,编写python读取xmind测试用例chatgtp+python+xmind

背景 有用xmind写测试用例的吧&#xff0c;统计一个xmind的条&#xff0c;需要花大量的时间&#xff0c;还有要统计有多少条冒烟的&#xff0c;多少条不通过的&#xff0c;还有通过的条数。 需求 快速使用python&#xff0c;写一个简单的脚本&#xff0c;统计所有xmind节点&…

【IP地址与子网掩码】网络杂谈(19)之IP地址分类与子网掩码的概念

涉及知识点 什么是子网掩码&#xff0c;IP地址的分类&#xff0c;子网掩码的概念&#xff0c;深入了解子网掩码与IP地址,A类&#xff0c;B类&#xff0c;C类&#xff0c;D类&#xff0c;E类ip地址范围。 原创于&#xff1a;CSDN博主-《拄杖盲学轻声码》&#xff0c;更多内容可…

Linux调试笔记

gdb调试----------------------------------------------------------------------------------------- CMakeFile.txt加入set(CMAKE_BUILD_TYPE Debug) gdb ./rknn_MNIST 打断点 b 110/main(行号/函数名) 单步调试 s&#xff08;step&#xff09; 单步跳过 n&#xff08;n…

计算机组成原理(2)_计算机基本组成

计算机组成系列文章目录 第一章 计算机的基本组成 1. 大致简介 2. 计算机基本组成 第二章 计算机的指令和运算 第三章 处理器设计 第四章 存储器和IO系统 文章目录 计算机组成系列文章目录前言参考资料一、组成架构&#xff08;冯/图&#xff09;1. 组成架构2. 冯诺依曼3. 图灵…

力扣 530. 二叉搜索树的最小绝对差 / 783. 二叉搜索树节点最小距离

题目来源 530&#xff1a;https://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/ 783&#xff1a; https://leetcode.cn/problems/minimum-distance-between-bst-nodes/ C题解1&#xff1a;递归法&#xff0c;中序遍历。通过中序遍历将二叉搜索树转…

【Android】Android类加载机制

ClassLoader介绍 任何一个 Java 程序都是由一个或多个 class 文件组成&#xff0c;在程序运行时&#xff0c;需要将 class 文件加载到 JVM 中才可以使用&#xff0c;负责加载这些 class 文件的就是 Java 的类加载机制。ClassLoader 的作用简单来说就是加载 class 文件&#xf…

echarts图表-实现中国地图的绘制

第一步&#xff1a;引入中国地图的json数据&#xff0c;初始化echarts的dom结构&#xff0c;使用registerMap方法加载地图数据&#xff08;注&#xff1a;echarts5.X版本后删除了中国地图的JSON&#xff0c;需自行下载JSON或降低echarts版本&#xff09; 第二步&#xff1a;传输…

React通过props的children实现插槽功能

可能会比较遗憾的说 React中并没有vue中的 slot 插槽概念 不过 可以通过props.children 实现类似功能 我们先创建一个React项目 在src下创建目录components 在下面创建一个dom.jsx组件 参考代码如下 import React from "react" export default class dom extends R…

Android学习日志 一、滚动视图的嵌套

文章目录 滚动视图的嵌套创建项目(前期准备)工程搭建编写XML正式代码 By-Round Moon 滚动视图的嵌套 说明:本博客是博主学习安卓开发的第一个案例。接下来会进行一系列的样例&#xff0c;含很多基础部分&#xff0c;各位观众老爷请见谅。 Android Studio 版本:2022.2.1 patch …

如何将MBR转为GUID?这方法易于使用且安全!

为什么要将MBR转为GUID(GPT)&#xff1f; MBR代表主引导记录&#xff0c;它使用Legacy BIOS分区表。而GPT磁盘&#xff0c;也就是GUID分区表的缩写&#xff0c;是一种引入了统一可扩展固件接口 (UEFI) 的新布局。GPT磁盘有2个主要优势&#xff1a; GPT磁盘每个分区…