目录
1.人力资源项目介绍
1.1 项目架构和解决方案
1.2 课程安排
1.3 课程具备能力
1.4 课程地址
2. 拉取项目基础代码
3.项目目录和入口文件介绍
4.App.vue根组件解析
5.基础设置settings.js和导航守卫permission.js
6.Vuex的结构
7.使用模板中的Icon图标
8.扩展-解析Icon图标的实现思路
9.导入样式资源并使用git管理
10.登录页的结构和表单
11.登录表单校验-实现
1.人力资源项目介绍
1.1 项目架构和解决方案
1.2 课程安排
1.3 课程具备能力
1.4 课程地址
- vue-element-admin文档地址:vue-element-admin
- 演示地址: https://panjiachen.github.io/vue-element-admin/
- 人力资源项目演示地址:人力资源后台管理系统
2. 拉取项目基础代码
- 拉取命令
$ git clone https://github.com/PanJiaChen/vue-admin-template.git heimahr
- 升级core-js版本到3.25.5
$ npm i core-js@3.25.5 # npm
$ yarn add core-js@3.25.5 # yarn
- 安装完整依赖
$ npm i # npm
$ yarn # yarn
- 启动命令在package.json中查看
$ yarn dev
- 需要检查VsCode本身的插件ESLint 和 Vutur
3.项目目录和入口文件介绍
- 项目目录
├── src # 源代码目录
│ ├── api # 所有请求
│ ├── assets # 主题 字体等静态资源
│ ├── components # 全局公用组件
│ ├── icons # 项目所有 svg icons
│ ├── layout # 全局 layout
│ ├── router # 路由
│ ├── store # 全局 store管理
│ ├── styles # 全局样式
│ ├── utils # 全局公用方法
│ ├── views # views 所有页面
│ ├── App.vue # 入口页面
│ ├── main.js # 入口文件 加载组件 初始化等
│ └── permission.js # 权限管理
│ └── settings.js # 配置文件
- 入口文件
4.App.vue根组件解析
- App.vue组件
- layout布局
5.基础设置settings.js和导航守卫permission.js
settings.js导出网站基础配置,包括:网站标题、固定header、显示logo
permission.js(权限),主要负责路由导航守卫
6.Vuex的结构
注意:人资资源项目主要针对**用户模块user **进行改造和重写
- Vuex的设计思想
1.页面交互状态(折叠侧边栏-固定头部)
2.使用全局状态Vuex根据功能拆分成不同的模块(modules)
3.进行状态管理通过getters建立对于模块中属性的快捷访问
7.使用模板中的Icon图标
- src/icons/svg目录下的图标都可以使用
- 图标文件名直接设置为svg-icon组件的iconClass属性
8.扩展-解析Icon图标的实现思路
- 引入目录所有的svg
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg componentVue.component('svg-icon', SvgIcon) //全局注册组件
// 扫描目录文件,是否扫描子目录 扫描的目标文本
const req = require.context('./svg', false, /\.svg$/)
//封建函数 req.keys是svg数组
// map循环的是每一项 svg图片 map(()=>{})
// req 能够引用图片到项目中,将所有的svg引入到项目中
console.log(req.keys());
const requireAll = requireContext => requireContext.keys().map(requireContext)
//调用函数
requireAll(req)
- 全局注册svg-icon组件
import SvgIcon from '@/components/SvgIcon'// svg componentVue.component('svg-icon', SvgIcon) //全局注册组件
// 这个组件根据传入的图标类名来显示对应的SVG图标,支持外部图标和普通SVG图标的显示和样式设置
<template><!--用于显示SVG图标。它根据传入的图标类名来决定显示的图标类型。 首先判断是否为外部图标(isExternal),外部图标使用一个div元素来显示,通过设置样式和绑定事件来实现如果是,则显示一个外部图标的样式,否则显示一个普通的SVG图标。--><divv-if="isExternal":style="styleExternalIcon"class="svg-external-icon svg-icon"v-on="$listeners"/><svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners"><!-- 其中,xlink:href属性指定了要引用的Symbol的ID。通过这种方式,我们可以轻松地在SVG中插入Symbol,并在需要时进行修改和更新。 --><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是可选的,用于指定额外的类名。className: {type: String,default: "",},},computed: {// isExternal用于判断图标是否为外部图标,isExternal() {return isExternal(this.iconClass);},// iconName用于生成图标的IDiconName() {return `#icon-${this.iconClass}`;},// svgClass用于生成SVG图标的类名,svgClass() {if (this.className) {return "svg-icon " + this.className;} else {return "svg-icon";}},// styleExternalIcon用于生成外部图标的样式。styleExternalIcon() {return {mask: `url(${this.iconClass}) no-repeat 50% 50%`,"-webkit-mask": `url(${this.iconClass}) no-repeat 50% 50%`,};},},
};
</script><style scoped>
/* 定义SVG图标 */
.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>
- loader插件打包svg
config.module// 定义一个名为'svg'的规则。.rule('svg')// 将'src/icons'目录添加到排除列表中,意味着该目录下的SVG文件不会被这个规则处理.exclude.add(resolve('src/icons'))// 结束对该规则的链式调用。.end()config.module//定义一个名为'icons'的规则。.rule('icons')// 指定该规则只匹配以'.svg'结尾的文件。.test(/\.svg$/)// 将'src/icons'目录添加到包含列表中,意味着只有该目录下的SVG文件会被这个规则处理。.include.add(resolve('src/icons'))// 结束对该规则的链式调用。.end()// 使用名为'svg-sprite-loader'的loader。.use('svg-sprite-loader')// 指定使用'svg-sprite-loader'来处理匹配到的文件。.loader('svg-sprite-loader')// 传递一些选项给'svg-sprite-loader',这里设置了生成的symbol的id格式为'icon-[name]',其中[name]会被替换为原始文件的名称。.options({symbolId: 'icon-[name]'})// 结束对loader的链式调用。.end()
- svg-icon引用svg的链接
- 知识扩展
1.了解:require.context(路径,是否扫描子目录, 正则匹配) 可以引入某个目录下的内容
require
我们平常
require
是在运行时加载模块并且生成一个对象,特点是每次引入一个,需要指定路径,不支持传入变量.代码试例:
require('./template/' + name + '.ejs');
在
webpack
中,webpack
为我们提供了require.context
这个 api,他和require
最大的区别就在于就是可以在一个路径下,获取一个特定的上下文,可以用正则去查找并导入多个模块让我们来看看什么是 require.context,具体的可以去官网看,
require.context
可以给这个函数传入三个参数:
- 一个要搜索的目录,
- 一个标记表示是否还搜索其子目录,
- 一个匹配文件的正则表达式。
语法如下:
const req = require.context('./svg', false, /\.svg$/)
2.了解:svg-sprite-loader打包了所有svg到一个svg标签上,将svg名称作为symbol标签的id属性
3.了解:svg-icon使用iconClass属性引用了symbol的id
SVG标签: SVG标签是HTML中用于嵌入矢量图形的主要标签。它允许我们使用XML语法创建可缩放的图形,这些图形可以在不失真的情况下调整大小。SVG标签可以包含各种形状、路径、文本和样式属性,使我们能够创建复杂的图形和动画效果。通过使用SVG标签,我们可以实现各种交互效果,如悬停、点击和动态变化。
Symbol标签: Symbol标签是SVG中的一个特殊元素,它允许我们定义可重用的图形片段。通过将图形定义为Symbol,我们可以在需要的地方多次使用它,而不必重复编写相同的代码。Symbol标签本身不会在页面上显示任何内容,它只是一个图形的容器。我们可以使用<use>标签来引用Symbol,并将其插入到文档中。
Use标签: Use标签用于在SVG中引用和插入Symbol。通过使用Use标签,我们可以在文档中多次重复使用相同的图形,从而实现代码的重用性和可维护性。Use标签的语法如下:
<svg><use xlink:href="#symbol-id"></use> </svg>
其中,xlink:href属性指定了要引用的Symbol的ID。通过这种方式,我们可以轻松地在SVG中插入Symbol,并在需要时进行修改和更新。
9.导入样式资源并使用git管理
- 将教学资源中的初始化**图片-样式-svg **拷贝到src目录下
因为项目是从github上拉取下来的,所以git记录了之前模版的信息,所以删除需要建立git
- 删除原有的.git文件
- 初始化仓库
$ git init # 初始化仓库
- 添加到暂存区
$ git add . # 添加到暂存区
- 提交本地仓库
$ git commit -m "初始化人力资源项目" # 提交本地仓库
接下来,同学们需要在gitee上新建一个自己的远程仓库,然后将本地的仓库推送到远程仓库托管
- 本地仓库配置远程仓库地址
$ git remote add origin <你的远程仓库地址> # 本地仓库配置远程仓库地址
- 推送到远程仓库
$ git push -u origin master # 推送到远程仓库
10.登录页的结构和表单
接下来需要实现登录页的表单结构和表单内容
- 拷贝登录页的基本结构布局-代码位置(src/views/login/index.vue)
<template><div class="login-container"><div class="logo" /><div class="form"><h1>登录</h1><el-card shadow="never" class="login-card"><!--登录表单--></el-card></div></div>
</template>
<script>
export default {name : "Login"
}
</script>
<style lang="scss">
.login-container {display: flex;align-items: stretch;height: 100vh;.logo {flex: 3;background: rgba(38, 72, 176) url(../../assets/common/login_back.png)no-repeat center / cover;border-top-right-radius: 60px;display: flex;flex-direction: column;align-items: flex-end;justify-content: center;padding: 0 100px;.icon {background: url(../../assets/common/logo.png) no-repeat 70px center /contain;width: 300px;height: 50px;margin-bottom: 50px;}p {color: #fff;font-size: 18px;margin-top: 20px;width: 300px;text-align: center;}}.form {flex: 2;display: flex;flex-direction: column;justify-content: center;padding-left: 176px;.el-card {border: none;padding: 0;}h1 {padding-left: 20px;font-size: 24px;}.el-input {width: 350px;height: 44px;.el-input__inner {background: #f4f5fb;}}.el-checkbox {color:#606266;}}
}
</style>
- 实现登录表单的结构
<el-card shadow="never" class="login-card"><!--登录表单--><!-- el-form > el-form-item > el-input --><el-form><el-form-item><el-input placeholder="请输入手机号" /></el-form-item><el-form-item><el-input placeholder="请输入密码" /></el-form-item><el-form-item><el-checkbox> 用户平台使用协议 </el-checkbox></el-form-item><el-form-item><el-button style="width: 350px" type="primary">登录</el-button></el-form-item></el-form></el-card>
- 提交代码
11.登录表单校验-实现
- 定义数据和校验规则
export default {name: 'Login'name: 'Login',data() {return {loginForm: {mobile: '',password: '',isAgree: false},loginRules: {mobile: [{required: true,message: '请输入手机号',trigger: 'blur'}, {pattern: /^1[3-9]\d{9}$/,message: '手机号格式不正确',trigger: 'blur'}],password: [{required: true,message: '请输入密码',trigger: 'blur'}, {min: 6,max: 16,message: '密码长度应该为6-16位之间',trigger: 'blur'}],// required只能检查 null "" undefinedisAgree: [{validator: (rule, value, callback) => {// rule规则// value检查的数据 true/false// callback 函数 执行这个函数// 成功执行callback 失败也执行callback(错误对象 new Error(错误信息))value ? callback() : callback(new Error('没有勾选用户平台协议'))}}]}}},methods: {login() {this.$refs.form.validate((isOK) => {if (isOK) {alert('校验通过')}})}}
}
</script>
- 绑定组件的对应属性
<el-form ref="form" :model="loginForm" :rules="loginRules"><el-form-item prop="mobile"><el-input v-model="loginForm.mobile" placeholder="请输入手机号" /></el-form-item><el-form-item prop="password"><el-input v-model="loginForm.password" show-password placeholder="请输入密码" /></el-form-item><el-form-item prop="isAgree"><el-checkbox v-model="loginForm.isAgree">用户平台使用协议</el-checkbox></el-form-item><el-form-item><el-button style="width:350px" type="primary" @click="login">登录</el-button></el-form-item>
</el-form>