基于vue3与element-plus制作Web端的产品文档说明书

大家好~ 我是前端uio,本文主要使用vue3和element plus 制作产品的文档说明书, 有什么疑问都欢迎私聊或者在评论区留言。如果需要开发web网页或者微信小程序都可以找我私聊,我会尽可能回答我了解的内容。


一、功能说明

1.目录

(1)多级目录

        相比于element-plus官方的示例,本文在使用多级菜单(menu)时,提取重复的逻辑,优化了嵌套结构,从而提高了代码的可读性以及可维护性。

(2)目录所有菜单内容展开

        如图所示为初始化页面时目录的效果,可以查看element-plus官方文档,使用default-active属性:页面加载时默认激活菜单的 index,使用default-openeds属性:默认打开的 sub-menu 的 index 的数组。

(3)目录中超出视图的内容可通过滑动滚动条查看

        使用div包着el-menu组件,在div的class类中先自定义设置可滚动的高度,再使用 overflow: scroll,即可实现。

2.产品文档说明书内容

(1)点击目录的菜单选项,滑动到指定内容(以置顶为例)

        i)获取dom元素

        ii)使用el-scrollbar中Exposes出来的其中一个setScrollTop函数(若想滑动到特定位置,可以使用scrollTo,具体见element plus官方文档

        iii)将dom的offsetTop传入setScrollTop函数

二、主要代码

1.目录主要代码(nav.vue)

/**
 * @name    { el-menu }
 * @info    { 菜单组件的嵌套优化 }
 * @author  { 前端uio 2024-5-15 }
 *
 * @select funtion => 选中菜单项的 index
 */
//目录主要代码
<template>
  <div class="nav">
    <el-menu
      :default-active="nav[0].children[0].index"
      :default-openeds="openList"

      class="el-menu-vertical-demo"
      @select="handleSelect"
    >
      <div v-for="(item, index) in nav" :key="index">
        <el-sub-menu
          v-if="item.type === 'sub-menu'"
          :key="index" :index="item.index"
        >
          <template #title>
            <span class="titleName">{{ item.title.text }}</span>
          </template>
          <div v-for="(child, childIndex) in item.children" :key="child.title">
            <el-sub-menu
              v-if="child.children"
              :key="childIndex"
              :index="child.index"
            >
              <template #title>
                {{ child.title }}
              </template>
              <div v-for="(childItem, childItemIndex) in child.children" :key="childItemIndex">
                <el-sub-menu :key="childItemIndex" :index="childItem.index">
                  <template #title>
                    {{ childItem.text }}
                  </template>
                  <div v-for="(children, childrenIndex) in childItem.children" :key="childrenIndex">
                    <el-menu-item
                      :index="children.index"
                    >
                      {{ children.desc }}
                    </el-menu-item>
                  </div>
                </el-sub-menu>
              </div>
            </el-sub-menu>
            <el-menu-item
              v-else :key="child.index"
              :index="child.index"
            >
              {{ child.title }}
            </el-menu-item>
          </div>
        </el-sub-menu>
        <div
          v-else-if="item.type === 'menu-item'"
        >
          <el-menu-item>
            <template #title>
              <el-icon><component :is="item.title.icon" /></el-icon>
              <span>{{ item.title.text }}</span>
            </template>
          </el-menu-item>
        </div>
      </div>
    </el-menu>
  </div>
</template>
<script setup>
import { nav, openList } from '../constants.ts'
const emits = defineEmits(['select'])
const handleSelect = (e) => {
  emits("select", e)
}

</script>

2.存放数据(constants.ts)

/**
 * @name    { typescript }
 * @info    { 菜单组件的数据 }
 * @author  { 前端uio 2024-5-15 }
 *
 * @export array => 数据驱动菜单组件
 */
// 菜单选项
export const nav = [{
  type: 'sub-menu',
  index: 'text',
  title: {
    icon: 'location',
    text: 'text1'
  },
  children: [
    {
      type: 'sub-menu',
      title: 'text-1',
      index: 'text-1'
    },
    {
      type: 'sub-menu',
      index: 'text-2',
      title: 'text-2'
    },
    {
      type: 'sub-menu',
      index: 'text-3',
      title: 'text-3'
    },
    {
      type: 'sub-menu',
      index: 'text-4',
      title: 'text-4'
    },
    {
      type: 'sub-menu',
      index: '1-5',
      title: '1-5',
      children: [{ type: 'sub-menu', index: '1-5-1', text: 'text',
        children: [{
          type: 'menu-item', index: '1-5-1-1', desc: 'text'
        },
        {
          type: 'menu-item', index: '1-5-1-2', desc: 'text'
        }]
      },
      { type: 'sub-menu', index: '1-5-2', text: 'text',
        children: [{
          type: 'menu-item', index: '1-5-2-1', desc: 'text'
        },
        {
          type: 'menu-item', index: '1-5-2-2', desc: 'text'
        },
        {
          type: 'menu-item', index: '1-5-2-3', desc: 'text'
        },
        {
          type: 'menu-item', index: '1-5-2-4', desc: 'text'
        }]
      },
      { type: 'sub-menu', index: '1-5-3', text: 'text',
        children: [{
          type: 'menu-item', index: '1-5-3-1', desc: 'text'
        },
        {
          type: 'menu-item', index: '1-5-3-2', desc: 'text'
        },
        {
          type: 'menu-item', index: '1-5-3-3', desc: 'text'
        }]
      },
      { type: 'sub-menu', index: '1-5-4', text: 'text',
        children: [{
          type: 'menu-item', index: '1-5-4-1', desc: 'text'
        },
        {
          type: 'menu-item', index: '1-5-4-2', desc: 'text'
        },
        {
          type: 'menu-item', index: '1-5-4-3', desc: 'text'
        }]
      }] }
  ]
}]

// 展开的子菜单
export const openList = [
  'text-5-1', 'text-5-2', '1-5', '1-5-1', '1-5-2', '1-5-3', '1-5-4'
]

3.产品内容说明书(content.vue)

     /**
     * @name    { el-scrollbar}
     * @info    { 产品说明书的主体内容 }
     * @author  { 前端uio 2024-5-15 }
     *
     * @ref  => 获取组件实例
     * @id   => 滑动到特定的id元素的位置
     */
    <!-- template内容 -->
    <div class="fileContent">
      <el-scrollbar
        ref="scrollView" :max-height="height"
        class="content"
      >
        <div id="fileContent">
          <text1 />
        </div>
        <div id="server">
          <server />
        </div>
        <div id="frameWork">
          <frameWork />
        </div>
        <div id="init">
          <init />
        </div>
        <div id="baseFunc">
          <baseFunc />
        </div>
      </el-scrollbar>
    </div>
     /**
     * @name    { proxy}
     * @info    { 获取element plus 组件exposes 出来的方法 }
     * @author  { 前端uio 2024-5-15 }
     *
     * @refs           => 获取组件实例
     * @setScrollTop   => 设置滚动条到顶部的距离
     */
<script setup>
import { ref, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()

const selectNav = ref("fileContent")

const isSelect = (e) => {
  selectNav.value = e
  handleScroll(selectNav.value)
}
const handleScroll = (select) => {
  let ele = document.getElementById(select)

  proxy.$refs.scrollView.setScrollTop(ele.offsetTop)
}

// 用于存储高度值
const navHeight = ref(0)
navHeight.value = window.innerHeight - 70
const height = `${navHeight.value}px`

</script>

4.注意事项

(1)设置多级目录选项

          i)若需要设置子选项,则使用el-sub-menu

         ii)若为最后一级的选项,则使用el-menu-item

        iii)若目录选项需要设置icon(图标),则使用具名插槽#title

(2)展开所有目录选项

         i)动态绑定需要展开的选项index

:default-openeds="openList"

(3) 设置滑动的位置

         i)为组件绑定id

         ii)getCurrentInstance()函数通过解构赋值获取proxy

const { proxy } = getCurrentInstance()

        iii)使用ref绑定el-scrollbar组件,从而获取组件实例

      <el-scrollbar ref="scrollView" />

        iv)获取element plus 组件exposes 出来的方法setScrollTop将id传入setScrollTop方法

  proxy.$refs.scrollView.setScrollTop(ele.offsetTop)

三、拓展与练习

1.水平方向的首页菜单

(1)点击菜单选项切换不同的路由

           i)水平菜单

           ii)路由切换

(2)菜单选项切换的动画

           i)鼠标悬浮或选中菜单选项时,字体加粗且显示下划线

           ii)页面初始化时,默认选中第一个菜单选项

2.代码示例

     /**
     * @name    { el-menu}
     * @info    { 横向菜单 }
     * @author  { 前端uio 2024-5-15 }
     *
     *
     * @default-active     => 设置加载时的激活项
     * @mode               => 设置为水平模式
     * @router             => 以index 作为 path 进行路由跳转 
     * @select    funtion  => 选中菜单项的 index
     */
<template>
  <div class="navBar">
    <span class="title">首页菜单</span>
    <el-menu
      default-active="/index"
      mode="horizontal"
      router
      class="titleMenu"
      @select="handleSelect"
    >
      <div v-for="(item,index) in menuNav" :key="index">
        <el-menu-item :index="item.index" :class="item.index===active?'active':''">
          {{ item.title }}
        </el-menu-item>
      </div>
    </el-menu>
  </div>
</template>
<script setup>
import { ref } from 'vue'
const active = ref('/index')
const handleSelect = (e) => {
  active.value = e
}

const menuNav = [
  {
    title: '首页',
    index: '/index'
  },
  {
    title: '菜单项1',
    index: '/file'
  },
  {
    title: '菜单项2',
    index: '/text2'
  },
  {
    title: '菜单项3',
    index: '/text3'
  },
  {
    title: '菜单项4',
    index: '/text3'
  }
]
</script>
<style scoped>
.navBar {
display: flex;
background-color: #3697c7;
width: 100%;
  .title {
    letter-spacing: 4px;
    font-size: 20px;
    font-weight: 800;
    color: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 650px;
    margin-right: 300px;
  }
  .titleMenu {
    width: 700px;
    letter-spacing: 4px;
    background-color: #3697c7;
    display: flex;
    justify-content: space-around;
    .el-menu-item {
      color: #e5e5e5;
      font-size: 18px;
      background-color: #3697c7;
    }
    .el-menu-item:hover , .active{
      color: #fff !important;
      background-color: #3697c7;
      font-weight: 800;
      border-bottom: 2px solid #fff;
      box-sizing: border-box;
    }
  }
}
</style>

3.视频展示

        可查看本人主页发布的《横向菜单路由切换》视频进行查看

4.具体实现步骤

(1)设置菜单选中效果

        :class="item.index===active?'active':''"

(2)动态绑定

        通过@select事件返回的index(开启router模式后index为路由路径)动态绑定菜单的选中效果

(3)获取菜单选项所在的样式类名class

        无法直接查看element plus封装的组件选项样式,可通过调试工具进行查看,这里的类名(class)为el-menu-item

四、总结与思考

1.滚动条的显示与隐藏

2.若目录上方有内容,如何让目录撑满视图(vh)

3.如何处理超出视图部分的内容(滚动显示)

  • 27
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值