VUE笔记(八)项目实战

一、后台首页

1、首页布局

用于布局的容器组件,方便快速搭建页面的基本结构:

<el-container>:外层容器。当子元素中包含 <el-header><el-footer> 时,全部子元素会垂直上下排列,否则会水平左右排列。

<el-header>:顶栏容器。

<el-aside>:侧边栏容器。

<el-main>:主要区域容器。

<el-footer>:底栏容器。

<template>
   <el-container>
      <!-- 侧边栏 -->
      <el-aside width="220px">asider</el-aside>
      <el-container>
          <el-header>header</el-header>
          <el-main>main</el-main>
      </el-container>
   </el-container>
</template>
2、顶部栏
<el-row type="flex" style="align-items:center">
    <el-col :span="6">
        <el-row>
            <el-col :span="6">
                <i class="el-icon-s-fold" style="font-size:24px" v-if="!isCollpase"></i>
                <i class="el-icon-s-unfold" style="font-size:24px" v-else></i>
                <i class="el-icon-refresh-left" style="font-size:24px"></i>
           </el-col>
          <el-col :span="18">
            <el-breadcrumb separator="/" style="line-height:20px">
                <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
                <el-breadcrumb-item>控制面板</el-breadcrumb-item>
                <el-breadcrumb-item>工作台</el-breadcrumb-item>
            </el-breadcrumb>
          </el-col>
       </el-row>
    </el-col>
    <el-col :span="4" :offset="14">
         <el-row type="flex" style="align-items:center">
              <el-col :span="8">
                  <el-avatar :size="45" src="https://woniuimage.oss-cn-                                                                  hangzhou.aliyuncs.com/woniuimage/teacher/20220222/abc7a6e787be41d0b12aa41e429b71d2.png" 
                             class="avatar"></el-avatar>
              </el-col>
              <el-col :span="8">个人中心</el-col>
                 <el-col :span="8">退出系统</el-col>
              </el-row>
      </el-col>
</el-row>

二、菜单栏

1、静态菜单
2、动态菜单
  • 更改request.js文件

需要在请求拦截器中为头信息中添加Authorization,它的值是从localStorage中获取的token的信息

axios.interceptors.request.use(config => {
    config.headers.Authorization=localStorage.getItem('token')
    return config
})
  • 在api/modules/users.js文件中编写获取权限菜单的方法

export default{
    getAuthMenus:()=>request.get('/menus/getAuthMenus')
}
  • 在Home页面中,在created生命周期函数中调用获取权限菜单的方法

export default {
  data(){
    return{
      menudata:[]
    }
  },
  methods:{
    async getAuthMenus(){
      let result=await this.$api.users.getAuthMenus() 
      console.log(result);
      this.menudata=result.data
    }
  },
  created(){
    this.getAuthMenus()
  }
}
  • 在页面中进行渲染

<el-menu 
    background-color="#202743" 
    text-color="#fff" 
    active-text-color="orange"
    :unique-opened="true">
    <!-- 使用v-for嵌套完成一二级菜单的渲染 -->
    <el-submenu :index="item._id" v-for="item in menudata" :key="item._id">
        <template slot="title">
            <i :class="item.icon"></i>
            <span>{{item.title}}</span>
        </template>
        <el-menu-item :index="subitem._id" v-for="subitem in item.children" :key="subitem._id">
            <i :class="subitem.icon"></i>
            <span slot="title">{{subitem.title}}</span>
        </el-menu-item>
    </el-submenu>            
 </el-menu>
3、路由鉴权
  • 在api/modules/users.js文件中编写获取用户信息的api方法

import request from '@/api/request'
​
export default{
    getUserInfo:()=>request.get('/users/getUserInfo')
}
  • 在router/index.js中通过导航独享守卫完成路由鉴权

{
        path:'/home',
        component:()=>import('@/views/Home.vue'),
        beforeEnter:async(to,from,next)=>{
          //从localstroage获取token信息
          let token=localStorage.getItem('token')
          if(!token){
            // Message.error('您还没有登录,请先登录')
            Vue.prototype.$message.error('您还没有登录,请先登录')
            router.replace('/login')
          }else{
            let result=await Vue.prototype.$api.users.getUserInfo()
            if(result.code){
                next()
            }
          }
        }
 }
  • 在request.js文件中对于401错误进行处理

axios.interceptors.response.use(response => {
    return response.data
}, ({ response }) => {
    if (response) {
        switch (response.status) {
            case 401:
                Message.error('您的token已失效,请重新登录') 
                router.replace('/login')
                break
            case 404:
                break
            case 500:
                break
        }
    }
})
4、菜单的路由跳转
  • 在Home.vue组件的el-menu中设置router="true"

<el-menu 
     background-color="#202743" 
     text-color="#fff" 
     active-text-color="orange"
     :unique-opened="true"
     :router="true">
</el-menu>
  • 在el-menu下的el-menu-item中将index的值改为subItem.path

 <el-menu-item :index="subitem.path" v-for="subitem in item.children" :key="subitem._id">
         <i :class="subitem.icon"></i>
         <span slot="title">{{subitem.title}}</span>
  </el-menu-item>
  • 在el-main中配置二级路由出口

<el-main>
     <router-view></router-view>
 </el-main>
  • 在router/index.js中配置动态路由操作

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home.vue'
Vue.use(VueRouter)
​
const addRoutes=async(data)=>{
  router.addRoute({
    path:'/home',
    component:Home,
    children:data.map(item=>{
      return{
        path:item.path.substring(item.path.lastIndexOf("/")+1),
        component:()=>import(`@/views${item.permission}.vue`)
      }
    })
  })
}
​
const routes = [
  {
    path: '/login',
    component: () => import('@/views/Login.vue')
  }
]
const router = new VueRouter({
  routes
})
router.beforeEach(async(to,from,next)=>{
  console.log('********全局守卫**********');
  if(to.path=="/login"){
    next()
  }else{
    let token=localStorage.getItem('token')
    if(!token){
      Vue.prototype.$message.error('您还没有登录,请先登录')
      router.replace('/login')
    }else{
      let result=await Vue.prototype.$api.users.getUserInfo()
      console.log('result',result);
      if(result.code){
        next()
        if(Vue.prototype.$code!=1){
          addRoutes(result.data.permissionList)
          Vue.prototype.$code=1
        }
      }
    }
  }
})
​
export default router
5、菜单折叠
  • 在Home.vue文件中定义数据isCollpase

export default {
  data(){
    return{
      isCollapse:false,
    }
  }
}
  • <el-header>区域添加折叠和展开按钮,并根据isCollapse的值控制这两个按钮的显示或隐藏

<el-aside>
     <i v-if="!isCollapse" class="el-icon-s-fold" style="margin-left:190px"></i>
     <i v-else class="el-icon-s-unfold" style="margin-left:40px"></i>
    <!--...其余代码省略-->   
</el-aside>
  • 为展开和折叠按钮添加绑定单击事件

<el-aside>
     <i v-if="!isCollapse" class="el-icon-s-fold" @click="toggleCollpase" style="margin-left:190px"></i>
     <i v-else class="el-icon-s-unfold" @click="toggleCollpase" style="margin-left:40px"></i>
    <!--...其余代码省略-->   
</el-aside>
methods: {
    toggleCollpase(){
      this.isCollapse=!this.isCollapse;
    }
}
  • <el-menu>标签中添加collpase属性来控制菜单的折叠或展开

<el-menu :collapse="isCollapse">
  • <el-aside>中动态设置菜单栏的宽度,同时删除掉之前style="width: 200px"

<el-aside :width="isCollapse?'68px':'220px'">
  • 取消切换动画

<el-menu :collapse-transition="false">

三、样式穿透

1、组件之间的样式冲突问题

默认情况下,写在.vue组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题

导致组件之间样式冲突的根本原因是

  • 单页面应用程序中,所有组件的DOM结构,都是基于唯一的index.html页面进行呈现的。

  • 每个组件的样式,都会影响整个index.html页面中的DOM元素。

2、scoped的底层实现原理

解决样式冲突问题的办法是在<style>标签之间添加一个scoped属性

<style scoped>
 
</style>

其实scoped的底层原理是使用了css的属性选择器来完成的。

<template>
    <h2 data-v-001>班级列表</h2>
</template>
<style>
  h2[data-v-001]{
    color: red;
  }
</style>
3、样式穿透

复制elementui案例中的样式,复制后边框出不来,要想解决样式穿透问题

样式穿透只存在于局部样式中,即<style>中添加了scoped属性

  • >>>/deep/:作用于CSS

  • ::v-deep:作用于SASS

<style lang="scss" scoped>
.avatar-uploader ::v-deep .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader ::v-deep .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>v
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值