拉取基础模板代码
git clone https://github.com/PanJiaChen/vue-admin-template.git
其他: core-js版本处理
安装依赖项
yarn
出现这种情况便是安装依赖成功
启动项目
我们在package.json中设定的dev执行命令
yarn dev
启动一下下
下载两个插件
此插件的作用就是帮我们格式化代码,如下图所示,在代码的后面加了一个分号,便提示错误信息
这种格式化的错误很好修改,只需要“Ctrl+Alt+L”即可(使用的webstore),会自动消失
如果是VSCode的话就下载ESLint和Vetur
除了src文件之外我们都可以理解为配置文件
我们会把请求单独抽离出来放在api文件目录下
抽离出来有个好处,哪个模块想用直接引用就好了
比如user.js文件按需导出了一些方法
import request from '@/utils/request'
export function login(data) {
return request({
url: '/vue-admin-template/user/login',
method: 'post',
data
})
}
export function getInfo(token) {
return request({
url: '/vue-admin-template/user/info',
method: 'get',
params: { token }
})
}
export function logout() {
return request({
url: '/vue-admin-template/user/logout',
method: 'post'
})
}
存放静态资源,比如图片
存放组件文件
Breadcrumb 面包屑组件
Hamburger 汉堡组件
SvgIcon 图标组件
这三个组件是公用组件
我们要实现图片注册、自动引用
layout 布局组件目录
router 路由目录
路由:地址和组件的映射。一个地址对应一个组件,但一个组件可能会对应多个地址
VUEX是状态管理框架,在store目录中存放的就是VUEX
存放一些全局样式
存放工具类
也是存放组件的目录,但是区别与components目录文件夹
views目录存放路由器组件
在router目录index.js文件中地址对应组件,对应的组件就是路由器组件,在views目录中
App.vue组件
汇总所有组件
https://blog.csdn.net/weixin_51351637/article/details/126733697
入口文件。当执行完npm run serve命令后会直接执行此文件
一般在这个文件引入一些我们常用的模块、实例化vue、指定容器、挂载路由、渲染根组件、注册Element-ui组件
https://blog.csdn.net/weixin_51351637/article/details/126733697
main.js组件将我们的根组件App.vue渲染到了页面上
那到底做了什么样的工作能够显示我们的登录/首页/布局?
如下所示,App.vue组件中代码
<template>
<div id="app">
<!--路由容器组件,一级路由-->
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
App.vue文件中有一个router-view一级路由容器,里面放置的是root里面的一级路由
然后“/”中里面还有二级路由
layout布局是怎么保证二级路由组件的显示呢?
/**
* Layout @/在vue中代表路径别名
* @ 符号表示当前目录的src
* @/ 表示src下的layout,而layout又是一个目录,所以会拉取index.vue文件
* 即index.vue组件就是我们的路由组件,会实现二级路由
* */
import Layout from '@/layout'
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index'),
meta: { title: 'Dashboard', icon: 'dashboard' }
}]
},
我们也可以分析一下layout中index.vue文件的代码,是如下所示的布局形式
放到我们的页面三个结构如下所示
app-main组件为什么可以展示二级路由?
在layout目录的index.vue文件下如下图所示:
我们可以再看一下components文件下AppMain.vue组件
并且在此处还有一个router-view组件(此时是二级组件)
可以看一下layout布局组件的总结
导出网站基础设置,保罗网站标题、固定header、显示logo
这个文件中导出了一个对象,里面有许多的属性是key:value的形式
module.exports = {
/**
* 标题
*/
title: '人力资源后台管理系统',
/**
* 是否固定我们的头部组件
*/
fixedHeader: false,
/**
* 是否显示侧边栏的logo
*/
sidebarLogo: false
}
如下所示我们的title
当fixedHeader的值是true时,下图所标注的地方不会随便下拉而看不到,而是一直固定在这里
当sidebarLogo的值为true的时候,就可以看到如下图所示的图标
此文件为了完成权限拦截,负责路由导航守卫
其实就是下面两个函数,路由前置守卫和路由后置守卫
路由前置守卫:路由跳转之前执行
路由后置守卫:路由跳转之后执行
// to到哪个组件
//from从哪个组件来
//next是在执行完一系列判断逻辑之后必须要执行哪个函数,只有执行了next,路由才能完成正常的跳转,完成跳转之后会执行路由后置守卫
async(to, from, next)
VUEX向外暴露了两个属性,一个modules和一个getters
我们只暴露两个属性说明我们项目的VUEX都放在modules模块中,而getters是向外暴露一些便捷的访问属性,并没有我们常见的state、mutation和action
modules我们称之为模块
getters我们称之为VueX里面的计算属性
index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'
Vue.use(Vuex)
const store = new Vuex.Store({
// 模块
modules: {
app,
settings,
user
},
// Vuex中的计算属性
getters
})
export default store
app和settings控制我们左侧导航的伸缩、控制header的固定、左侧导航的logo展示
user是需要我们做用户权限信息的部分
getters是模块属性的意思,而getters中属性都来自于modules模块中state属性
然后我们可以看到getters.js文件中导出了一些属性
state是根状态
state.app.sidebar是取app模块属性
state.user.token是取user模块属性
所以说我们的getters只是做了一个便捷访问,更便捷的访问模块中的属性
此项目中Vuex的设计思想
图片和图标是有区别的
图片使用png或者gpg,而图标一般是svg形式
图标的目的是装饰和点缀,也没有其他的作用
我们将上面的图标进行使用的时候还需要借助一个组件,此组件已经将图标注册好了,图标就可以正常显示了
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>
怎么使用?
<!--使用svg-incon组件-->
<!--设置iconClass属性=“文件名(没有后缀)”-->
<svg-icon icon-class="dashboard"></svg-icon>
src/icons/svg目录下的图标都可以使用
图标文件名直接设置为svg-icon组件的iconClass属性
在main.js文件实际上我们引入了icon这个目录,并且在这个目录中有一个index.vue文件
查看一下icon目录下index.vue文件
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// 全局注册组件。这也就是为什么后面我们可以直接使用svg-icon
Vue.component('svg-icon', SvgIcon)
//require.context(要扫描的目标目录,是否扫描子目录,要扫描的目标文件,是一个正则表达式,以.svg结尾的文件) 扫描目录中的文件
//最终返回值req是是一个函数
const req = require.context('./svg', false, /\.svg$/)
//requireAll一个函数
//req.keys()的值是我们所扫描的所有的文件
//map是循环每一个项,也就是每一个svg图片,并且map的参数是一个回调函数
//req函数能够引用图片到项目中,如果svg有一百个,那这个map就执行100次
const requireAll = requireContext => requireContext.keys().map(requireContext)
//调用了函数
//将所有的svg都引用到项目中
requireAll(req)