头部

退出功能

默认头像

  1. // 短路写法
  2. <img :src="userInfo.user_pic || defImg" alt="" class="avatar" />
  3. // 三元运算符
  4. <img :src="userInfo.user_pic?userInfo.user_pic : defImg" alt="" class="avatar" />
  5. <script>
  6. // 导入一个图片
  7. import defImg from '@/assets/logo.png'
  8. export default {
  9. name: 'Main',
  10. data () {
  11. return {
  12. // 赋值到data变量中 键值对一样可以简写
  13. defImg
  14. }
  15. }
  16. </script>

获取登录用户信息,渲染到页面

配置请求

  1. // 获取登录人信息
  2. export function getUserInfoApi () {
  3. //这里没有传入需要的参数,因为可以请求拦截器中统一配置
  4. return request.get('/my/userinfo')
  5. }
  6. // 在子模块中导入该函数,并再次封装
  7. import { loginApi, getUserInfoApi } from '@/Api/index'
  8. export default {
  9. // 开启命名空间
  10. namespaced: true,
  11. actions: {
  12. async getUserInfo () {
  13. await getUserInfoApi()
  14. }
  15. }
  16. }
  1. created () {
  2. // 直接访问user模块的getUserInfo方法
  3. this.$store.dispatch('user/getUserInfo')
  4. }

发送请求之后发现请求为401 ( Unauthorized 译为 未授权的)image.png
这种情况一般是缺少验证信息,因为这里没有配置请求头里的token
image.png

配置请求头

  1. // axios网站复制
  2. axios.interceptors.request.use(function (config) {
  3. // 在发送请求之前做些什么
  4. return config;
  5. }, function (error) {
  6. // 对请求错误做些什么
  7. return Promise.reject(error);
  8. });
  9. // 箭头函数写法
  10. axios.interceptors.request.use( (config) => {
  11. // 发送请求之前执行代码
  12. return config
  13. })

config参数:控制台输出可以看到
image.png
添加请求头config.headers = token(具体什么名,看接口文档)
token存储在vuex中,js中调用vuex的数据,需要导入vuex实例
导入后的实例相当于组件中的this.$store
给添加请求头加一个判断,/my开头的接口需要token请求
config.url可以拿到请求接口,使用startsWitn方法判断uel是不是/my开头的

  1. // 导入vuex的实例
  2. import Store from '@/store/index'
  3. import axios from 'axios'
  4. // 定义新axios实例
  5. const request = axios.create({
  6. // 配置跟路径
  7. baseURL: 'http://big-event-vue-api-t.itheima.net'
  8. })
  9. // 导出新实例
  10. export default request
  11. // 配置请求拦截器
  12. request.interceptors.request.use((config) => {
  13. console.log(config)
  14. // /my开头的接口需要token请求,所以使用startsWitn判断uel是不是/my开头的
  15. if (config.url.startsWith('/my')) {
  16. // store 是vuex实例
  17. // state.模块名.state变量
  18. config.headers.Authorization = Store.state.user.token
  19. }
  20. // 返回请求配置,不然外面获取不到服务器发送过来的数据
  21. return config
  22. })

将获取到的用户信息存储,渲染到页面中

  1. // 用户模块中 定义一个state变量用来存储用户信息
  2. export default {
  3. // 开启命名空间
  4. namespaced: true,
  5. state: {
  6. userInfo: {}
  7. },
  8. mutations: {
  9. // 存贮用户数据
  10. setuserInfo (state, payload) {
  11. state.userInfo = payload
  12. }
  13. },
  14. // 组件中 mapState 导入模块中的变量到computed,在页面渲染
  15. import { mapState } from 'vuex'
  16. computed: {
  17. ...mapState('user', ['userInfo'])
  18. },

左侧菜单

  1. <el-menu
  2. default-active="1"
  3. class="el-menu-vertical-demo"
  4. background-color="#23262E"
  5. text-color="#fff"
  6. active-text-color="#409EFF"
  7. unique-opened
  8. >
  9. <!-- 不包含子菜单的“一级菜单” -->
  10. <el-menu-item index="1"><i class="el-icon-s-tools"></i>一级菜单</el-menu-item>
  11. <!-- 包含子菜单的“一级菜单” -->
  12. <el-submenu index="2">
  13. <template slot="title">
  14. <i class="el-icon-s-tools"></i>
  15. <span>一级菜单</span>
  16. </template>
  17. <el-menu-item index="2-1"><i class="el-icon-star-on"></i>二级菜单</el-menu-item>
  18. <el-menu-item index="2-2"><i class="el-icon-star-on"></i>二级菜单</el-menu-item>
  19. <el-menu-item index="2-3"><i class="el-icon-star-on"></i>二级菜单</el-menu-item>
  20. </el-submenu>
  21. </el-menu>

选中高亮

element组件不支持,在页面中查找到当前选中的元素类名,覆盖样式
需要加上最高权重不然不会覆盖!important

  1. .el-aside {
  2. background-color: #23262e;
  3. .el-menu-item.is-active,
  4. // 鼠标移入也高亮
  5. .el-menu-item:hover {
  6. background: orange !important;
  7. color: #fff !important;
  8. // 图标颜色
  9. i {
  10. color: #fff;
  11. }
  12. }
  13. }

获取菜单数据并渲染

获取数据

  1. import request from '@/utils/request'
  2. // 写法1
  3. // export function getMenu () {
  4. // return request.get('/my/menus')
  5. // }
  6. // 写法2
  7. export const getMenu = () => request.get('/my/menus')
  1. //导入封装的请求
  2. import { getMenuApi } from '@/Api/menu'
  3. export default {
  4. name: 'Main',
  5. data () {
  6. return {
  7. menus: []
  8. }
  9. },
  10. methods: {
  11. // 定义获取菜单方法
  12. async getMenu () {
  13. // 解构
  14. const { data } = await getMenuApi()
  15. console.log(data)
  16. // 获取到的变量赋值
  17. this.menus = data.data
  18. }
  19. },
  20. created () {
  21. this.getMenu()
  22. }
  23. }

动态渲染菜单

  • 有两种情况
    • 1.不包含子菜单一级菜单
    • 2.包含子菜单的一级菜单
  • 需要再<templat>空标签来v-for(打包的时候 html页面不解析)
    • 同时使用 v-if 来判断
      • 如果循环的是第一种那么第二种的表标签就隐藏
      • 如果循环的是第二种那么第一种的表标签就隐藏
      • children是null (false) ,取反为true,就会循环第一个了,children有值结果为true,取反后false不满足if条件就循环第二个了
        1. <el-menu
        2. default-active="1"
        3. class="el-menu-vertical-demo"
        4. background-color="#23262E"
        5. text-color="#fff"
        6. active-text-color="#409EFF"
        7. unique-opened
        8. router
        9. >
        10. <template v-for="item in menus">
        11. <!-- 不包含子菜单的“一级菜单” -->
        12. <el-menu-item
        13. v-if="!item.children"
        14. :key="item.indexPath"
        15. :index="item.indexPath"
        16. ><i :class="item.icon"></i>{{ item.title }}</el-menu-item
        17. >
        18. <!-- 包含子菜单的“一级菜单” -->
        19. <el-submenu v-else :key="item.indexPath" :index="item.indexPath">
        20. <template slot="title">
        21. <i :class="item.icon"></i>
        22. <span>{{ item.title }}</span>
        23. </template>
        24. <el-menu-item
        25. v-for="child in item.children"
        26. :key="child.indexPath"
        27. :index="child.indexPath"
        28. ><i :class="child.icon"></i>{{ child.title }}</el-menu-item
        29. >
        30. </el-submenu>
        31. </template>
        32. </el-menu>