笔记来源:拉勾教育 - 大前端就业集训营
文章内容:学习过程中的笔记、感悟、和经验
构建Vue项目
- 查看vue版本:
Vue -V - 创建项目结构:
vue create lagou-backstage-cwn - 选择项目使用配置,这里选择自定义配置
- 选择需要使用的插件
- ◉
Choose Vue veron- 选择则后期手动选择Vue版本(默认2.XX,我们也暂时使用2.XX) - ◉
Babel - babel功能 - ◉
Router- vueRouter路由 - ◉ `
- ◉
CSS Pre-processors- css预编译 - ◉
Linter / Formatter- 代码风格管理工具
- ◉
- 询问要使用的vue版本,这里选择2.X
- 询问router是否使用history模式,这里不使用,输入n回车
- 询问css编译器类型,这里暂时选择
Sass/SCSS (with dart-sass) - 选择代码校验风格,这里暂时选择
ESLint + Standard config - 询问什么时候进行代码风格校验功能,两个都选(保存时和git提交时)
- 询问把配置内容单独存放还是存放在
package.json,这里选择单独文件。路遇后期管理 - 询问是否存储以上配置信息,这里暂时输入n先不存储
- 回车执项目创建,期间可能会提示git是否上传的询问,选择不上传或者确定 13. 项目创建完毕 olo v```````q1a Q
- 进入目录,
cd....... - 运行预览
npm run sever
加入git版本管理功能
注意:以下操作都要基于你已经安装了git,如果没安装会出问题,先安装git,别问我怎么知道的
-
打开**.gitignore文件可以看到这里已经配置了上传忽略掉node_modules和/dist两个文件夹**的文件(上面第12步操作)如上面没有操作需要手动书写
.DS_Store node_modules /dist ....... -
运行
git status检查git仓库状态,提示On branch master,nothing to commit, working tree clean说明项目已经处于git管理之下了 -
在github或者开源中国创建一个仓库,获取仓库地址
-
输入
git remote add 仓库别名 仓库地址把仓库地址存起来,可以使用git remote -v查看所有别名 -
输入
git push -u 仓库别名 master把项目提交到仓库中的master分支,这里添加-u之后我们可以直接使用git push直接把项目提交到仓库中,就不用写全git push 仓库别名 master了
目录结构说明
- 根目录
- node_modules - 依赖包目录,内部存放项目依赖的包
- public - 静态资源目录,打包的时候都直接复制到打包目录中,不经过webpack处理
- src - 资源目录
- assets - 资源目录,存放开发时可能用到的图片等文件
- components - 公共组件目录,内部存放所有公共组件
- router - 路由模块目录,下面的index.js存放路由模块相关功能
- store - vueX功能目录,后面会讲解
- view - 视图存储目录,存储路由相关页面组件
- App.vue - 根组件,相当于之前使用的根实例
- Main.js - 入口文件。里面引入模块创建vue实例
- .browserslistrc - 目标浏览器范围,后期进行一些浏览器兼容处理会用到,暂时不用管
- .editorconfig - 编辑器的配置文件
- .eslintrc.js - eslint规则配置文件,代码风格设置
- .gitignore - git插件帮我们创建的,可用来忽略node_modules内容
- babel.config.js - 关于babel配置文件
- package-lock.json - npm文件,记录相关包信息
- package.json - npm文件,记录相关包信息
- README.md - 信息文件,可以书写文档信息
调整初始目录
删除掉一些初始化文件,根据需求进行目录的新增和调整
- 删除src目录下一些自动生成的文件
- 删除assets目录下的logo.png文件,我们用不到
- 删除components下面的所有组件的组件,我们用不到
- 删除view下的所有组件,我们用不到
- 在src目录下创建新目录
- 新建services目录 - 存放接口模块功能
- 新建styles目录,存放全局样式
- 新建utils目录,存放工具相关模块
- 修改文件
- 删除app.vue中router-link引入的组件,这些组件都被我们删除了,并且所有样式
- 删除router目录下的index.js文件的routes中的路由映射规则,删除顶部引入的Home组件,组件已经被我们删除了这些也用不到了
一些cli中的注意事项
- cli中引入模块都适用import引入
- 引入的插件需要使用
Vue.use(引入的插件)注册给vue才能使用 - main.js下面的
import router from './router' 和 import store from './store'都使用了文件夹没有写具体引入那个文件,那么默认使用的就是目录下的index.js文件
代码规范和代码风格
- (本项目使用)JavaScript Standard Style (standardjs.com)代码规范,比较常见、流行
- GitHub - airbnb/javascript: JavaScript Style Guide代码规范
Standard已经在上面创建项目时安装
使用.eslintrc.js文件将规范落地,把规范引入到vue项目的.eslintrc.js文件中,程序就会强制使用此规范,如果书写违反规范则报错
module.exports = {
root: true,
env: {
node: true
},
// 让规范落地
extends: [
// vue官方提供的eslint插件,检查约束vue相关代码,可以在 vue->风格指南查看
'plugin:vue/essential',
// 我们使用的代码风格校验工具
'@vue/standard'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}
出现报错处理问题
- 查看报错信息,获取报错信息的最后一个单词,例如
12:22 error Extra semicolon semi则获取semi - 进入ESlint中文官网:ESLint - Pluggable JavaScript linter - ESLint中文
- 点击规则查看全部规则代码对应的错误,可以尝试搜索即可定位具体错误信息
**自定义校验规则 - **.eslintrc.js
如果我们想更改一些规则我们就需要自定义代码校验规则,更改规则之后需要重启serve
我们只需要在.eslintrc.js文件的rules中添加配置即可
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// 自定义规则:允许书写分号
'semi': 'off'
}
具体方法可以查看Configuring ESLint - ESLint中文中的Configuring Rules
正常情况下,我们使用eslint需要我们手动配置规则,但是由于我们使用了standard帮助我们快速引入了一些规则,从而简化了我们很多工作
Element组件库
优秀的第三方组件库,非常适合开发后台管理系统的项目
官网地址:
- 基于vue3.0:Element - 网站快速成型工具 (gitee.io)
- 基于vue2.0:Element - 网站快速成型工具
**安装使用 **
具体方法官方文档写的很清楚,可以查看官方网站 - 组件
-
项目安装element-ui为开发依赖:
npm i element-ui -S -
在src目录下的main.js引入element和主题文件(暂时先完整引入,后面会介绍按需引入)
-
将element注册为vue插件
//main.js ........... // 引入element-ui import ElementUI from 'element-ui' // 引入element-ui主题文件 import 'element-ui/lib/theme-chalk/index.css' // 将element-ui注册为vue插件 Vue.use(ElementUI) .................. -
测试是否可用element
<!-- App.vue文件 --> <template> <div id="app"> <h1>拉钩教育</h1> <router-view /> <!-- 引入element组件试一下,直接复制即可 --> <el-row> <el-button>默认按钮</el-button> <el-button type="primary">主要按钮</el-button> <el-button type="success">成功按钮</el-button> <el-button type="info">信息按钮</el-button> <el-button type="warning">警告按钮</el-button> <el-button type="danger">危险按钮</el-button> </el-row> </div> </template> ..............
样式处理
这里主要是设置全局样式和修改element主题的相关设置
-
在src-styles下新建四个scss文件(这里使用scss预编译器)
-
index.scss- vue引入的文件,可以看作入口文件// 引入variables文件获取所有变量,一些看不懂的可以先不看,后面会讲 @import './variables.scss'; // 设置html样式 html { font-family: $font-family; -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); // better Font Rendering -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } // 设置body样式 body { margin: 0; background-color: $body-bg; } // 更改 element 主题色(写法参考element官方文档) $--color-primary: $primary-color; $--color-success: $success-color; $--color-warning: $warning-color; $--color-danger: $danger-color; $--color-info: $info-color; // 改变 icon 字体路径变量,必需 $--font-path: '~element-ui/lib/theme-chalk/fonts'; // 引入 element 默认主题文件(样式文件) @import '~element-ui/packages/theme-chalk/src/index'; // node_modules/element-ui/packages/theme-chalk/src/common/var.scss // overrides // .el-menu-item, .el-submenu__title { // height: 50px; // line-height: 50px; // } .el-pagination { color: #868e96; } // components .status { display: inline-block; cursor: pointer; width: .875rem; height: .875rem; vertical-align: middle; border-radius: 50%; &-primary { background: $--color-primary; } &-success { background: $--color-success; } &-warning { background: $--color-warning; } &-danger { background: $--color-danger; } &-info { background: $--color-info; } } -
mixin.scss- 混入,把一些需要复用的样式放在这里(暂时空置) -
reset.scss- 重设样式文件,以后我们修改样式直接在这里修改(暂时空置) -
variables.scss- 定义一些变量,作用同less// 预设一些变量 $primary-color: #40586F; $success-color: #51cf66; $warning-color: #fcc419; $danger-color: #ff6b6b; $info-color: #868e96; // #22b8cf; $body-bg: #E9EEF3; // #f5f5f9; $sidebar-bg: #F8F9FB; $navbar-bg: #F8F9FB; $font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
-
-
修改
main.js,因为我们已经在index.scss中引入了element主题文件,所以可以去掉............ // 引入element-ui主题文件,因为index.scss里面已经引入了这个文件,这里就不需要再引入了,直接注释掉 // import 'element-ui/lib/theme-chalk/index.css' // 引入自定义样式文件 import './styles/index.scss' .................
共享全局样式变量
如果我们在其他文件,比如vue组件中想要使用variables.scss中的样式变量,那么我们就需要设置全局的样式变量共享
局部引入
// 不设置全局共享,只在单个组件引入
<style lang="scss">
// 引入sass文件
@import "~@/styles/variables.scss";
// 使用样式变量
div {
background: $primary-color;
}
</style>
问题:如果组件比较多那么就要引用多次,消耗资源,我们可以设置全局的共享变量
全局共享
访问vuc-cli官网 - 指南 - 开发 - css相关 - 向预处理器 Loader 传递选项
-
根目录新建配置文件
vue.config.jsmodule.exports = { // css配置项 css: { loaderOptions: { // 样式编译器类型 scss: { // 这里的作用的当程序读取scss格式css之前在代码前面添加一段话,我们在这里让每次加载scss之前都引入样式变量文件,就可以实现全局共享 // 因为我们使用的是8.xx版本的sass,所以要写成prependData,否则应该写为additionalData prependData: `@import '~@/styles/variables.scss';` } } } } -
重启sever,注意只要修改了配置文件,都需要重启才能生效
-
设置完上面配置文件之后,不需要在每次书写css时引入文件了,webpack会自动引入
路由相关功能处理
基础功能设置
具体需求
- 设置初始的路由组件,组件结构后期书写
- 书写相应的路由结构,实现切换url可以切换到相应组件
- 添加一个布局容器组件,将侧边栏、顶栏、内容展示区全部都书写在这个组件内,后续所以组件也都是这个组件的子组件
- 添加一个404页面,当用户访问不存在的页面的时候切换到这个页面
创建文件结构
我们这里按照侧边栏设计在views下面创建文件夹,每个组件创建一个文件夹,每个文件夹下面创建一个index.vue文件
- login - 登陆页组件
- layout - 布局容器组件,里面包裹除登陆页外的所有组件
- home - 主页组件
- rolelist - 角色列表组件
- menu - 菜单组件
- resources - 资源列表组件
- course - 课程管理组件
- user - 用户管理组件
- Advertising - 广告列表组件
- Advertising-space - 广告位管理组件
注意:权限管理和广告管理并不需要路由,内部的二级菜单才需要路由
<!-- 组件通用文件结构,暂时不需要写内容,后面会根据需求书写内容 -->
<template>
<div>我是主页内容</div>
</template>
<script>
export default {
name: 'home'
}
</script>
<!-- layout布局组件,这里面主要承载一些固定结构和其他组件,所以需要在这里添加一个router-view -->
<template>
<div>我是layout布局容器
<router-view></router-view>
</div>
</template>
<script>
export default {}
</script>
路由规则书写
// 引入vue和router
import Vue from 'vue'
import VueRouter from 'vue-router'
// 引入需要使用到的组件
import login from '@/views/login/index'
import layout from '@/views/layout/index'
import home from '@/views/home/index'
import rolelist from '@/views/role/index'
import menu from '@/views/menu/index'
import resources from '@/views/resources/index'
import course from '@/views/course/index'
import user from '@/views/user/index'
import Advertising from '@/views/Advertising/index'
import AdvertisingSpace from '@/views/Advertising-space/index'
import error from '@/views/404/index'
// 将router导入为vue插件
Vue.use(VueRouter)
// 设置路由规则
// 这里把除login和404之外的其他组件都设置为layout的子路由
const routes = [{
// 登陆模块,单独为一个页面
path: '/login',
component: login
}, {
path: '/',
component: layout,
// 给布局容器添加子路由,其他子路由要全部都在布局容器下显示
children: [{
// homepath直接设置为空,这样/就也会显示home的内容,把hone作为登陆后的首页内容
path: '',
component: home
}, {
path: '/role',
component: rolelist
}, {
path: '/menu',
component: menu
}, {
path: '/resources',
component: resources
}, {
path: '/course',
component: course
}, {
path: '/user',
component: user
}, {
path: '/Advertising',
component: Advertising
}, {
path: '/AdvertisingSpace',
component: AdvertisingSpace
}, {
// 404模块,单独为一个页面
path: '*',
component: error
}]
}]
// 创建vuetouter实例
const router = new VueRouter({
routes
})
// 导出实例
export default router
以上两项书写完基本就可以修改url后缀切换组件的功能了
功能优化
问题
- 如果功能比较多,打包后文件会比较大,因为所有组件都被打包到一块了
- 在加载的时候我们没有访问的组件也会被加载,导致效率变低
- 打包后的名字是随机生成的,我们想让每个模块的名字对应到文件名上
解决方案
- 路由懒加载:路由懒加载 | Vue Router (vuejs.org),会将每个组件要分开打包,访问的时候才会加载对应组件
- 使用webpack魔法注释的方式给打包文件设置命名,可以将每个包打包后的文件名对应组件名,便于功能调试
// 引入vue和router
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
// 设置路由规则
// 这里把除login和404之外的其他组件都设置为layout的子路由
// 将使用的模块全部替换为懒加载路由并使用webpack的魔法注释功能设置打包后的文件名前缀
const routes = [{
// 登陆模块,单独为一个页面
path: '/login',
component: () => import(/* webpackChunkName:'login' */ '@/views/login/index')
}, {
path: '/',
component: () => import(/* webpackChunkName:'layout' */ '@/views/layout/index'),
// 给布局容器添加子路由,其他子路由要全部都在布局容器下显示
children: [{
// homepath直接设置为空,这样/就也会显示home的内容,把hone作为登陆后的首页内容
path: '',
component: () => import(/* webpackChunkName:'home' */ '@/views/home/index')
}, {
path: '/role',
component: () => import(/* webpackChunkName:'role' */ '@/views/role/index')
}, {
path: '/menu',
component: () => import(/* webpackChunkName:'menu' */ '@/views/menu/index')
}, {
path: '/resources',
component: () => import(/* webpackChunkName:'resources' */ '@/views/resources/index')
}, {
path: '/course',
component: () => import(/* webpackChunkName:'coures' */ '@/views/course/index')
}, {
path: '/user',
component: () => import(/* webpackChunkName:'user' */ '@/views/user/index')
}, {
path: '/Advertising',
component: () => import(/* webpackChunkName:'Advertising' */ '@/views/Advertising/index')
}, {
path: '/AdvertisingSpace',
component: () => import(/* webpackChunkName:'AdvertisingSpace' */ '@/views/Advertising-space/index')
}, {
// 404模块,单独为一个页面
path: '*',
component: () => import(/* webpackChunkName:'404' */ '@/views/404/index')
}]
}]
// 创建vuetouter实例
const router = new VueRouter({
routes
})
// 导出实例
export default router
布局处理
设置布局容器模块layout中固定的模块内容,包括侧边栏顶栏,内容区不需要在这里设置(在其他组件内部书写),这里的组件单独书写组件.vue文件
注意:组件的一些样式功能设置可以参考组件页面底部文档
布局容器
设置页面整体的布局,这里设置左右分栏,然后右侧分上下栏
<template>
<!-- 布局容器 -->
<el-container>
<!-- 侧边栏 -->
<el-aside width="200px">侧边栏</el-aside>
<!-- 右侧 -->
<el-container>
<!-- 顶部 -->
<el-header>顶栏</el-header>
<!-- 内容展示区 -->
<el-main>内容展示区</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
// 设置三个区域背景色
.el-container {
height: 100vh
}
.el-aside {
background-color: #545c64;
}
.el-header {
background: #fff;
}
.el-main {
background-color: #e9eef3;
}
</style>
侧边栏
侧边栏组件单独写在lauout 》components 〉app-aside.vue中
<template>
<!-- 使用element的导航菜单组件 -->
<!-- efault-active="1" 默认选中第一个导航
class="el-menu-vertical-demo" 类名
background-color="#545c64" 背景色
text-color="#fff" 文字颜色
active-text-color="#ffd04b" 选中后文字颜色
router 激活router功能,设置el-menu-item的index="路由"可实现点击跳转
unique-opened 只保持一个子菜单的展开 -->
<el-menu
default-active="1"
class="el-menu-vertical-demo"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
router
unique-opened>
<!-- 包含子菜单的导航写在el-submenu中 -->
<el-submenu index="1">
<!-- template为导航名,点击不会跳转 -->
<template slot="title">
<!-- element中的小图标组件 -->
<i class="el-icon-location"></i>
<span>权限管理</span>
</template>
<!-- 实际导航菜单写在el-menu-item-group的el-menu-item中 -->
<el-menu-item-group>
<!-- 开启router后设置导航菜单的index属性可以设置点击后跳转的路由 -->
<el-menu-item index="/role">角色列表</el-menu-item>
<el-menu-item index="/menu">菜单列表</el-menu-item>
<el-menu-item index="/resources">资源列表</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-menu-item index="/course">
<i class="el-icon-menu"></i>
<span slot="title">课程管理</span>
</el-menu-item>
<el-menu-item index="/user">
<i class="el-icon-document"></i>
<span slot="title">用户管理</span>
</el-menu-item>
<el-submenu index="4">
<template slot="title">
<i class="el-icon-location"></i>
<span>广告管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="/Advertising">广告列表</el-menu-item>
<el-menu-item index="/AdvertisingSpace">广告位列表</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</template>
<script>
export default {
}
</script>
<style>
</style>
顶栏
顶栏组件单独写在lauout 》components 〉app-header.vue中
<template>
<!-- 创建一个元素包裹全部顶栏 -->
<div class="header">
<!-- 面包屑导航,这里没有设置任何功能,后期会对这里进行修改 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>活动管理</el-breadcrumb-item>
<el-breadcrumb-item>活动列表</el-breadcrumb-item>
<el-breadcrumb-item>活动详情</el-breadcrumb-item>
</el-breadcrumb>
<!-- 下拉菜单 -->
<el-dropdown>
<span class="el-dropdown-link">
<!-- 把文字换成头像,尺寸35 -->
<el-avatar :size="35" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png"></el-avatar>
<!-- 右侧箭头 -->
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<!-- 下拉菜单选项,现在是静态值,后期会设置 -->
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>用户信息</el-dropdown-item>
<el-dropdown-item divided>登出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
// 容器高度、flex布局、居中对齐
.header {
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
// 下拉菜单头像区域设置flex布局,居中对齐
.el-dropdown-link {
display: flex;
align-items: center;
}
}
</style>
布局容器引入组件
将侧边栏和顶栏两个组件引入到lauout 》index.vue中并应用
<template>
<!-- 布局容器 -->
<el-container>
<!-- 侧边栏 -->
<el-aside width="200px">
<!-- 引入侧边栏组件 -->
<appAside></appAside>
</el-aside>
<!-- 右侧 -->
<el-container>
<!-- 顶部 -->
<el-header>
<!-- 引入顶栏组件 -->
<appHeader></appHeader>
</el-header>
<!-- 内容展示区 -->
<el-main>
<!-- 这里作为路由组件的展示区 -->
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</template>
<script>
// 引入侧边栏和顶栏组件
import appAside from './components/app-aside'
import appHeader from './components/app-header'
export default {
name: 'layout',
components: {
// 把两个组件注册进来
appAside,
appHeader
}
}
</script>
<style lang="scss" scoped>
// 设置三个区域背景色
.el-container {
height: 100vh
}
.el-aside {
background-color: #545c64;
}
.el-header {
background: #fff;
}
.el-main {
background-color: #e9eef3;
}
</style>
接口处理 - 封装请求模块
注意:我们这里使用的传递参数的方式是urlencoded格式,文档写错了,所以我们使用post请求的时候需要改写一下data数据为名=值&名=值....的形式
使用前台接口文档和后台接口文档进行数据的获取,这里需要使用axios插件
-
安装aixos插件
npm install axios -
创建request文件夹,在src > utils目录下
// 引入axios import axios from 'axios' // 创建axios实例,并设置通用属性 const request = axios.create({ // 超时时间 - 2s timeout: 2000, // 默认前缀 baseURL: '' }) // axios拦截器,在发起请求之前 request.interceptors.request.use(config => { // 根判断传入的 url 前缀,设置不同的 baseURL config.baseURL = /^\/front/.test(config.url) ? 'http://edufront.lagou.com' : 'http://eduboss.lagou.com' // 返回新的配置对象 return config }) // 导出实例 export default request -
尝试使用模块
<template> <div id="app"> <router-view /> <!-- 引入element组件试一下 --> </div> </template> <script> // 引入接口模块 import request from '@/utils/request' // 在这里尝试使用一下接口模块 request({ // 使用get获取 method: 'get', // 获取地址 url: '/front/course/getAllCourse' }).then(res => { // 打印返回的数据看一下 console.log(res) }) export default {} </script> <style lang="scss"> </style>