欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[vue]利用router动态渲染菜单项和子菜单项

程序员文章站 2022-07-14 18:25:36
...

目录

非动态渲染的代码:

Home.vue组件

路由配置router.js 

动态渲染菜单项

Home.vue

router.js配置

通过数据库进行菜单动态渲染.....待更新


非动态渲染的代码:

Home.vue组件

<template>
  <div>
    <el-container>
       <el-aside width="200px">
          <el-menu @select="menuClick">
            <el-submenu index="1">
              <template slot="title">
                <i class="el-icon-location"></i>
                <span>导航一</span>
              </template>
                <el-menu-item index="/home/test1">选项1</el-menu-item>
                <el-menu-item index="/home/test2">选项2</el-menu-item>
            </el-submenu>
          </el-menu>
        </el-aside>
        <el-main>
          <router-view/>
        </el-main>
    </el-container>
  </div>
</template>

<script>
export default {
  name: "Home",
  methods: {
    //菜单**回调
    /**
     * index:选中菜单项的index,在这里我们用作为跳转路径
     * indexPath:选中菜单项的index path
     */
    menuClick(index){
        //路由跳转
        this.$router.push(index)
    },
  
    },
  },
};
</script>

路由配置router.js 

非完整代码,忽略了import 和Vue.use(VueRouter)

const routes = [{
    path: '/'
    ,name: 'Login'
    ,component: Login
  },
  {
    path: '/home'
    ,name: '导航一'
    ,component: Home
    ,children: [{
        path: '/test1'
        ,name: Test1'
        ,component: Test1
      },
      {
        path: '/test2'
        ,name: 'Test2'
        ,component: Test2
      }
    ]
  },
]

 这种方式每次新添加一个菜单项都需要我们去在Hone.vue中添加,然后在router.js配置路由.比较麻烦点.下面我们就将利用vue中的$router获取到router.js中的配置项,然后去动态的渲染Home.vue中的菜单项和子菜单项的信息.这样每次我们只需要修改router.js里面的东西就可以了,不用再去修改Home.vue中的内容了

动态渲染菜单项

Home.vue

使用this.$router.options.routes获取到router.js中各项路由配置的信息,其中的每一个item都是一个路由配置项.

hidden:标识位,表示是否渲染该项路由信息

<template>
  <div>
    <el-container>
      <el-header class="homeHeader">
        <div class="title">人事管理</div>
        <el-dropdown class="userInfo" @command="commandHandler">
          <span class="el-dropdown-link">
            {{ user.name }}<i><img :src="user.userface" alt="" /></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <!-- 每个下拉框的item中的command相当于id一样用于标记每个item -->
            <el-dropdown-item command="userinfo">个人中心</el-dropdown-item>
            <el-dropdown-item command="setting">设置</el-dropdown-item>
            <el-dropdown-item command="logout" divided>
              退出登录</el-dropdown-item
            ><!--divided表示分割线 -->
          </el-dropdown-menu>
        </el-dropdown>
      </el-header>

      <el-container>
        <el-aside width="200px">
          <el-menu @select="menuClick">
            <el-submenu index="1" v-for="(item,index) in this.$router.options.routes" :key="index" v-if="!item.hidden">
              <template slot="title">
                <i class="el-icon-location"></i>
                <span>{{item.name}}</span>
              </template>
                <el-menu-item :index="child.path" v-for="(child,indexj) in item.children" :key="indexj">{{child.name}}</el-menu-item>
            </el-submenu>
          </el-menu>
        </el-aside>
        <el-main>
          <router-view/>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
export default {
  name: "Home",
  methods: {
    //菜单**回调
    /**
     * index:选中菜单项的index,在这里我们用作为跳转路径
     * indexPath:选中菜单项的index path
     */
    menuClick(index){
        this.$router.push(index)
    },
  },
};
</script>

router.js配置

const routes = [{
    path: '/'
    ,name: 'Login'
    ,component: Login
    ,hidden:true
  },
  {
    path: '/home'
    ,name: '导航一'
    ,component: Home
    ,hidden:false   //此处的hidden只是个标记相当于bool flag,并不会把该路由隐藏
    ,children: [{
        path: '/test1'
        ,name: '选项一'
        ,component: Test1
      },
      {
        path: '/test2'
        ,name: '选项二'
        ,component: Test2
      }
    ]
  },
]

通过数据库进行菜单动态渲染.....待更新

代码优化v-for  v-if同时使用性能不太好

上面的是同时使用v-for和v-if,下面这个优化后的代码通过计算属性完成对this.$router.options.routes的过滤,将结果再给v-for使用,

<template>
  <div>
    <el-container>
      <el-header class="homeHeader">
        <div class="title">人事管理</div>
        <el-dropdown class="userInfo" @command="commandHandler">
          <span class="el-dropdown-link">
            {{ user.name }}<i><img :src="user.userface" alt="" /></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <!-- 每个下拉框的item中的command相当于id一样用于标记每个item -->
            <el-dropdown-item command="userinfo">个人中心</el-dropdown-item>
            <el-dropdown-item command="setting">设置</el-dropdown-item>
            <el-dropdown-item command="logout" divided>
              退出登录</el-dropdown-item
            ><!--divided表示分割线 -->
          </el-dropdown-menu>
        </el-dropdown>
      </el-header>

      <el-container>
        <el-aside width="200px">
          <el-menu  router>
            <el-submenu index="1" v-for="(item,index) in menus" :key="index" >
              <template slot="title">
                <i class="el-icon-location"></i>
                <span>{{item.name}}</span>
              </template>
                <el-menu-item :index="child.path" v-for="(child,indexj) in item.children" :key="indexj">{{child.name}}</el-menu-item>
            </el-submenu>
          </el-menu>
        </el-aside>
        <el-main>
          <router-view/>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
export default {
  name: "Home",
  data() {
    return {
      //存入浏览器的本地session域中
      user: JSON.parse(window.sessionStorage.getItem("user")),
    };
  }, //data-end
  computed:{
    //在计算属性这里进行了过滤(相当于使用了v-if),然后再将过滤后的值给v-for使用
      menus(){
        let arr=[''];
        arr = this.$router.options.routes.filter(item=>{
          return item.hidden==false;
        })
        console.log(arr);
        return arr;
      }
  },
  methods: {
    //菜单**回调
    /**
     * index:选中菜单项的index,在这里我们用作为跳转路径
     * indexPath:选中菜单项的index path
     * 如果给menu配置一个router属性,就不用写menuClick这个点击事件了:router:会自动将index作为跳转路径进行跳转
     */
    // menuClick(index){
    //     this.$router.push(index)
    // },
    commandHandler(cmd) {
      if (cmd == "logout") {
        //confirm确定框
        this.$confirm("确认退出登录, 是否继续?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        })
          .then(() => {
            //确认时触发

            //向后端发送/logout
            this.getRequest("/logout");
            window.sessionStorage.removeItem("user"); //清空sessionStorage中的值
            this.$router.replace("/"); //回到登录页面
          })
          .catch(() => {
            //取消时触发
            this.$message({
              type: "info",
              message: "已取消操作",
            });
          });
      }
    },
  },
};
</script>

<style>
.homeHeader {
  background-color: #409eff;
  display: flex;
  /* 竖直方向上居中 */
  align-items: center;
  /*在弹性盒对象的 <div> 元素中的各项周围留有空白*/
  justify-content: space-between;
  padding: 0px 15px;
  box-sizing: border-box;
}

/* header中的'人事管理'字体设置 */
.homeHeader .title {
  font-size: 30px;
  font-family: 华文行楷;
  color: #ffffff;
}

/* 在鼠标放在右上角的抽屉式dropdown时,鼠标变为手指 */
.homeHeader .userInfo {
  cursor: pointer;
}

.el-dropdown-link img {
  width: 48px;
  height: 48px;
  border-radius: 24px;
  margin-left: 8px;
}
.el-dropdown-link {
  display: flex;
  align-items: center;
}
</style>