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

文章介绍了一种在Vue.js中实现自定义滚动条的方法,通过ElementPlus库中的slider组件和Affix组件,创建了一个竖向滚动条并将其与页面滚动绑定。同时,文章提到了如何构建菜单并与内容标题关联,实现点击跳转,以及添加返回顶部功能,增强了用户体验。
摘要由CSDN通过智能技术生成

起因

在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>


好的,以下是使用Vue3和Element Plus实现手机端侧边菜单栏的步骤: 1. 安装Vue3和Element Plus 首先,你需要安装Vue3和Element Plus。你可以通过npm或yarn安装它们。具体安装命令如下: ``` npm install vue@next npm install element-plus@next ``` 或者 ``` yarn add vue@next yarn add element-plus@next ``` 2. 创建侧边菜单组件 接下来,你需要创建一个侧边菜单组件。你可以使用Element Plus的Menu组件来实现。以下是一个基本的侧边菜单组件示例: ``` <template> <div class="sidebar-menu"> <el-menu :default-active="$route.path" class="el-menu-vertical-demo" router> <el-menu-item index="/"> <i class="el-icon-menu"></i> <span>首页</span> </el-menu-item> <el-menu-item index="/about"> <i class="el-icon-info"></i> <span>关于我们</span> </el-menu-item> <el-menu-item index="/contact"> <i class="el-icon-phone"></i> <span>联系我们</span> </el-menu-item> </el-menu> </div> </template> <script> import { defineComponent } from 'vue' export default defineComponent({ name: 'SidebarMenu', }) </script> <style> .sidebar-menu { height: 100%; background-color: #f0f2f5; padding: 20px; } </style> ``` 在这个示例中,我们使用了Vue Router来处理路由。我们还使用了Element Plus的Menu组件来创建菜单项。 3. 在App组件中引入侧边菜单组件 接下来,你需要在App组件中引入侧边菜单组件。以下是一个基本的App组件示例: ``` <template> <div class="app"> <el-container> <el-aside width="200px"> <sidebar-menu></sidebar-menu> </el-aside> <el-container> <router-view></router-view> </el-container> </el-container> </div> </template> <script> import { defineComponent } from 'vue' import SidebarMenu from './components/SidebarMenu.vue' export default defineComponent({ name: 'App', components: { SidebarMenu, }, }) </script> <style> .app { height: 100%; } </style> ``` 在这个示例中,我们使用了Element Plus的Container和Aside组件来创建一个侧边菜单栏一个主内容区域。我们还引入了我们之前创建的侧边菜单组件。 4. 完成 现在,你已经创建好了一个基本的手机端侧边菜单栏。你可以根据你的需求自定义样式和菜单项。 希望这可以帮助到你!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值