用Vue写一个简单好看的菜单组件(Vue实战系列)

简介: 用Vue写一个简单好看的菜单组件(Vue实战系列)

前端开发中,Vue.js已经成为一个非常流行的框架,它以其简洁的语法和强大的功能吸引了大量的开发者。今天,我们将一起使用Vue.js来创建一个简单而美观的菜单组件。

一、准备工作

在开始之前,请确保你已经安装了Vue.js。你可以通过Vue CLI来创建一个新的Vue项目,或者在你的现有项目中引入Vue.js。

需求

  1. 实现一个左边栏菜单,菜单只包括两层;
  2. 点击出现水波纹效果;
  1. 激活效果:有一个绿球小点,标识激活的菜单,顶层菜单被激活时左边出现浅色激活标志;

二、实现

1. 新建一个菜单组件whrmenu

组件接收的参数

我们希望可以定制小球的颜色,菜单数据,父级菜单激活的侧边框颜色

  props: {
    //菜单数据必输是数组 包含 url title icon children
      menu: {
        type: Array,
        required: true,
      },
      //父级激活左边阴影颜色
      pletcolor: {
        type: String,
        default: "#856ab5",
      },
      //小球颜色
      pointcolor: {
        type: String,
        default: "#1ab3a3",
      },

  },

这个菜单长这个样子,菜单的数据:

  menu: [
        {
          title: "题库管理",
          url: "/index/questionlist",
          icon: "el-icon-files",
          children: [
            {
              title: "题库列表",
              url: "/index/question/questionlist",
            },
          ],
        },
        {
          title: "活动管理",
          url: "/index/activity",
          icon: "el-icon-help",
          children: [
            {
              title: "活动列表",
              url: "/index/activity/activitylist",
            },
          ],
        },
        {
          title: "系统设置",
          url: "/index/sys",
          icon: "el-icon-setting",
          children: [
            {
              title: "用户管理",
              url: "/index/sys/user",
            },
          ],
        },
      ],

2. 拿到这个菜单,我们需要处理一下,如果menu有子菜单,那么就给加一个isexpand的属性,方便之后的做展开操作。

用一个计算属性修改一下menu

每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。

如果你这样做了,Vue 会在浏览器的控制台中发出警告。

这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:

  menus(){
      let menus = this.menu.map(item=>{
        if(item.children){
          item.isexpand = false;
        }
        return item
      })
      return menus
    }

3. vue的template部分模版代码

<div class="whr-menu">
      <div
          v-for="(item,index) in menus"
          :key="index"
      >
        <div
            v-ripple
            class="whr-pmenu-item"
            :class="{activeMenu:activeItem == item.url}"
            @click="clickitem(item,index)"
        >
          <div style="display:flex;">
            <div style="width:30px">
              <i
                  :class="item.icon"
                  style="margin-right:20px"
              ></i>
            </div>
            <div>
              {{ item.title }}
            </div>
            <div
                class="xiaoqiu"
                v-show="!item.isexpand && pgreen == item.url"
                :style="{ backgroundColor: pointcolor }"
            ></div>
          </div>

        </div>

        <div
            v-if="item.children"
            class="childrendiv"
            :class="{havechildren:item.isexpand}"
        >
          <div
              v-ripple
              class="whr-sbmenu-item"
              :class="{activesbMenu:activesbItem == sb_item.url}"
              @click="clicksbitem(sb_item,item)"
              v-for="(sb_item,sb_index) in item.children"
              :key="sb_index"
          >
            {{ sb_item.title }}
            <div
                class="xiaoqiu"
                v-show="$route.path == sb_item.url"
                :style="{ backgroundColor: pointcolor }"
            ></div>
          </div>
        </div>
      </div>

    </div>

4. 菜单的点击事件

  clickitem(item,index) {
      this.menus[index].isexpand = !item.isexpand;
      this.activeItem = item.url;
      if (item.children) {
        //有子菜单,设置子元素高度
        this.activeLength = item.children.length * 49 + 20 + "px";
      }
      this.$emit("dianp", item);
      console.log("当前激活父级菜单", this.activeItem);
    },
    clicksbitem(item, pitem) {
      //点击子菜单
      this.activesbItem = item.url;
      this.activeItem = pitem.url;
      this.$emit("dianc", {item, pitem});
    },

点击父级菜单和点击子菜单的逻辑我先写的不一样,以后可以简化再改,主要记录一下当前菜单的url;

父级菜单的这个小绿点有些麻烦,当激活的菜单是这个父级菜单的子菜单而且这个父级菜单没有展开的时候才加这个小绿点。

5. 做一个计算属性,看看当前激活的菜单在不在这个父级菜单里面,返回这个绿点应该在的位置:

//父级菜单绿点位置
    pgreen() {
      let u = [];
      u = this.menus.filter(item=>{
        let xu = []
        if(item.children.length>0){
          xu = item.children.filter(i=>{
            return i.url == this.$route.path
          })
          if(xu.length>0){
            return true
          } else {
            return false
          }
        }else {
          return item.url == this.$route.path
        }
      })
      return u[0].url
    },

使用Vue.js创建一个简单而美观的菜单组件

在前端开发中,Vue.js已经成为一个非常流行的框架,它以其简洁的语法和强大的功能吸引了大量的开发者。今天,我们将一起使用Vue.js来创建一个简单而美观的菜单组件。

三、组件解析

  1. 模板部分:我们使用了一个无序列表来显示菜单项,每个菜单项都是一个链接。我们使用了Vue的v-for指令来循环遍历items数组,并为每个菜单项生成一个列表项。我们还使用了v-bind指令(简写为:)来动态绑定classkey属性。
  2. 脚本部分:我们在data函数中定义了一个items数组来存储菜单项,以及一个currentIndex变量来跟踪当前选中的菜单项。我们还定义了一个selectItem方法来更新currentIndex的值。
  3. 样式部分:我们为菜单组件添加了一些基本的样式,包括背景颜色、内边距、文字颜色等。我们还为当前选中的菜单项添加了一个不同的背景颜色和文字颜色。

四、使用菜单组件

现在,你可以在你的Vue应用程序中使用这个菜单组件。首先,你需要在你的父组件中导入并注册这个组件,然后在模板中使用它。

<template>
  <div>
    <Menu />
    <!-- 其他内容 -->
  </div>
</template>

<script>
import Menu from './Menu.vue';

export default {
  components: {
    Menu
  }
};
</script>

五、总结

通过以上的步骤,我们成功地创建了一个简单而美观的菜单组件。这个组件使用了Vue.js的一些基本功能,包括模板语法、数据绑定和事件处理。你可以根据你的需求对这个组件进行扩展和定制,例如添加子菜单、下拉菜单等功能。希望这篇文章能对你有所帮助!

喜欢的小伙伴留言点赞关注吧!

相关文章
|
5天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
5天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
4天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉
|
4天前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。自学前端2年半,熟悉JavaScript与Vue,正向全栈方向发展。博客内容涵盖Vue基础、列表展示及计数器案例等,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
|
JavaScript
Vue - 实战疑点总结
1.注册全局组件(是一个单vue页面组成的一个组件,而不是现拼的template结构) 结构: 代码:main.js import UserList from './components/UserList' Vue.
2196 0
|
5天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
5天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
6天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
6天前
|
存储 JavaScript
Vue 组件间如何通信
Vue组件间通信是指在Vue应用中,不同组件之间传递数据和事件的方法。常用的方式有:props、自定义事件、$emit、$attrs、$refs、provide/inject、Vuex等。掌握这些方法可以实现父子组件、兄弟组件及跨级组件间的高效通信。
|
11天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发