Vue3+Element-Plus 动态加载主页Aside(左侧)菜单数据 二五

1. 通过接口动态获取左侧菜单数据

1.1 获取接口前的注意事项

1. 按照接口文档要求,除了登录接口外,需要授权的API 必须要在请求头中使用 Authorization 字段提供 token 令牌

  • 意思是说,访问接口必须得到服务器授权才能正常调用。

2. 如何获取服务器的授权认证。

  • 前面章节已经讲过,登录成功后。服务器端会返回一个登录成功后的( token)令牌,这个token 令牌就是权限认证的字段 (Authorization)
  • 所以在请求一些授权API时,必须在请求头中使用 (Authorization)字段,Authorization 字段 的值等于token 令牌的字符串

(6条消息) Vue3+Element-Plus 登录功能实现成功后的行为 十六_码侬人生-CSDN博客https://blog.csdn.net/weixin_39237340/article/details/121525604

3. 如何在请求头中添加 Authorization (权限认证)字段

  • 通过 Axios 拦截器添加 Authorization 字段
  • 原理:在Axios 请求拦截器中获取 token 令牌的字符串,再赋值给 Authorization 字段,从而保证请求时拥有获取数据的权限

3.1 如何为Axios 添加请求拦截器,并挂载一个自定义属性

// 请求拦截器
axios.interceptors.request.use(config => {
  // 为请求头对象,添加 Token 验证的 Authorization 字段
  config.headers.Authorization = window.sessionStorage.getItem('token')
  // 在最后必须 return config
  return config
})

3.2 请求拦截器原理解析

  1. 导入了axios 包后,通过axios调用interceptors 属性,该属性有一个成员属性叫requestrequest就是一个请求拦截器。那么可以通过use 属性为request 请求拦截器挂载一个回调函数。这个回调函数作用是,对发送的请求进行预处理。
  2. 也就是说,只要通过axios 向服务器发起数据请求,那么在请求期间必然会优先调用 use 函数进行数据的预处理。

 总结:

  • 请求拦截器相当于预处理的过程,预处理的对象是:本次的请求。

3.3 接下来对设置的请求对象 config 进行详细讲解,它包含了多个属性

  1.  config 对象中,包含了headers 属性,它就是一个请求头 ,但是它并没有Authorization 字段

 2. 接下来,需要给请求头headers ,通过自定义拦载器为它挂载一个Authorization 字段

3. 刷新页面,再来查看字段已添加成功。但是Authorization 的值为什么是空呢,因为在登录期间,服务器还没有给用户颁发 token 令牌 ,因此在这里它默认就是空。

4. 如果登录之后,再去调用其他接口 ,例如左侧菜单接口。再去监听请求的话,Authorization 值肯定不为空了。而是一个真正的 token 令牌了。

 总结

  • 服务器接受请求时,判断Authorization 是否符合要求。如果符合要求,才会进行响应。如若不符合要求,或者是说 Authorization 值为空,服务器就驳回本次请求。
  • 通过axios 配置了请求拦截器,为每一次的api 请求挂载了自定义的一个Authorization 请求头,确保了能正常访问调用有权限的API

4. 发起请求,获取左侧数据菜单

4.1 根据左侧菜单文档

  • get 请求
  • 路径 menus

 4.2 如上图,服务器响应的大对象中,包含在 data meta 两个属性。其中meta 状态码等于200 证明请求成功。请求成功后,data 中包含了服务器所返回的菜单列表,每一个菜单都是由id,authName,path,children 属性组成。children属性 代表有二级菜单。每一个二菜单也都是由id,authName,path,children 属性组成。 

  1. 请求左侧思路:当界面加载前,就应该立即获取左侧菜单数据。
  2. 通过vue 生命周期函数created  来实现

    3. 如上,通过使用花括号进行解构赋值,把data 属性解构出来并重命名为 res 进行接收

4.3 数据获取成功后,如何渲染在页面中呢?

1. 渲染思路:获取到数据后,需要挂载在 data 中。所以需要在data 中定义一个数据接收对象。该数据接收对象需要和返回的data 数据属性一至。例如。返回的data 是一个数组,那么定义的数据接收对像 menulist 也应当是一个数组。

2. 渲染左侧菜单

2.1 通过上面解构赋值后,已成功把获取到的左侧菜单数据保存在 menulist 中

 1. 接下来,根据 menulist 中保存的数据进行绘制左侧菜单UI 结构

 1.1 如何绘制

 首先,根据数据结构进行分析,所有的一级菜单数据保存在data 中。每一个一级菜单中,通过children 属性又嵌套了二级菜单

 1.2 绘制思路,通过双层 for 循环进行解析

  1. 外层 for 循环主要负责渲染一级菜单
  2. 内层 for 循环主要负责渲染二级菜单

1.3 Home.vue 页面代码实现

  1. 首先,渲染一级菜单。为一级菜单添加 v- for 指令进行循环。其中每一个v -for 指令尽量提供一个key 唯一值

   1.1 刷新查看页面效果,有5条数据循环出来了,但是文本写死了。所以我们应该把每一项对应的 authName 属性,当做显示的文本名称。

 1.2 接下来,为一级菜单中的span 标签动态绑定一个名称属性。

  1.3 再次刷新页面,效果都已经正常渲染出来了

 1.4 为了防止页面点击一个时,全部展开的现象。需要给一级菜单 el-submenu 每一项添加一个index 唯一值。

小技巧:

  • 动态的数据绑定,在属性前面加冒号
  • el-submenu 的index 唯一值,必须是字符串,不接收数值。所以转换成字符串的简单方式是在后面拼接一个空字符串

2. 接下来,渲染二级菜单。

2.1 二级菜单的渲染,应该是循环所有一级菜单的children 属性

 

 2.2 二级菜单渲染代码实现

 2. 最终效果

 3. Home.vue 页面代码

<template>
  <el-container class="home_container">
    <!-- 头部区域 -->
    <el-header>
      <div>
        <img src="../assets/heima.png" alt="" />
        <span>电商后台管理系统</span>
      </div>
      <el-button type="info" @click="logout">退出</el-button>
    </el-header>
    <!-- 页面主体区域 -->
    <el-container>
      <!-- 侧边栏 -->
      <el-aside width="200px">
        <!-- 侧边栏菜单区域 -->
        <el-menu
        active-text-color="#ffd04b"
        background-color="#545c64"
        text-color="#fff">
        <!-- 一级菜单 -->
        <el-submenu :index="item.id+''" v-for="item in menulist" :key="item.id">
          <!-- 一级菜单模板区域 -->
          <template #title>
            <el-icon><location /></el-icon>
            <span>{{item.authName}}</span>
          </template>
          <!-- 二级菜单 -->
          <el-menu-item :index="subItem.id+''" v-for="subItem in item.children" :key="subItem.id">
          <template #title>
            <el-icon><iconMenu /></el-icon>
            <span>{{subItem.authName}}</span>
          </template>
          </el-menu-item>
        </el-submenu>
      </el-menu>
      </el-aside>
      <!-- 右侧内容主体区域 -->
      <el-main>Main</el-main>
    </el-container>
  </el-container>
</template>
<script>
export default {
  data () {
    return {
      // 左侧菜单数据对象
      menulist: []
    }
  },
  created () {
    this.getMenuList()
  },
  methods: {
    logout () {
      window.sessionStorage.clear()
      this.$router.push('/login')
    },
    // 获取所有的菜单数据
    async  getMenuList () {
      const { data: res } = await this.$http.get('menus')
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      // 成功了,进行赋值
      this.menulist = res.data
      console.log(res)
    }
  }
}
</script>
<style lang="less" scoped>
.home_container {
  height: 100%;
}
.el-header {
  background-color: #363d40;
  // 给头部设置一下弹性布局
  display: flex;
  // 让它贴标左右对齐
  justify-content: space-between;
  // 清空图片左侧padding
  padding-left: 0;
  // 按钮居中
  align-items: center;
  // 文本颜色
  color: #fff;
  // 设置文本字体大小
  font-size: 20px;
  // 嵌套
  > div {
    // 弹性布局
    display: flex;
    // 纵向上居中对齐
    align-items: center;
    // 给文本和图片添加间距,使用类选择器
    span {
      margin-left: 15px;
    }
  }
}
.el-aside {
  background-color: #313743;
}
.el-main {
  background-color: #e9edf1;
}
</style>

4.main.js 页面代码

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import installElementPlus from './plugins/element'

// 导入字体图标
import './assets/font/iconfont.css'
// 导入全局样式表
import './assets/css/global.css'

import axios from 'axios'
// 配置请求根路径
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
// 请求拦截器
axios.interceptors.request.use(config => {
  console.log(config)
  // 为请求头对象,添加 Token 验证的 Authorization 字段
  config.headers.Authorization = window.sessionStorage.getItem('token')
  // 在最后必须 return config
  return config
})
const app = createApp(App)
installElementPlus(app)
app.config.globalProperties.$http = axios
app.use(router).mount('#app')

以上自出:【黑马程序员】前端开发之Vue项目实战_Element-UI【配套源码+笔记】_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1x64y1S7S7?p=35&spm_id_from=pageDriver

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小丫头呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值