目录
一、Mock.js
1.1 mockjs介绍
1.2 mock.js安装与配置
1.2.1 安装mock.js
1.2.2 引入mock.js
1.3 mock.js的使用
1.3.1 准备模拟数据
1.3.2 定义拦截路由
1.3.3 测试
二、首页导航栏左侧菜单搭建
2.1 自定义界面组件 (完整代码)
2.2 配置路由
2.3 组件显示折叠和展示图标
2.4 总线完成组件通信
2.5 效果展示
一、Mock.js
1.1 mockjs介绍
Mock.js是一个用于生成随机数据和模拟接口请求的JavaScript库。它可以帮助开发人员在前端开发过程中模拟后端接口的返回数据,以便进行前端页面的开发和测试。
Mock.js有两个重要的特性风靡前端:
- 数据类型丰富
Mock.js提供了一套简单易用的API,可以用于生成各种类型的随机数据,如字符串、数字、布尔值、日期等。开发人员可以使用Mock.js定义接口的返回数据结构,并生成符合该结构的随机数据。
- 拦截Ajax请求
通过拦截Ajax请求,Mock.js可以截获前端发送的请求,并根据预先定义的规则返回模拟的数据。延时响应功能可以模拟网络延迟,以便测试页面在不同网络条件下的表现。动态数据生成功能可以根据请求参数生成符合条件的随机数据。不需要修改既有代码,就可以拦截Ajax请求,返回模拟的响应数据。
1.2 mock.js安装与配置
1.2.1 安装mock.js
npm i mockjs -D
tips:在前面也讲到了-S,-G两种命令行的选项,这里综合讲解一下这三种的区别
- -S选项用于启动开发服务器
- -D选项用于在启动开发服务器后自动打开浏览器
- -G选项用于生成代码或文件。它们分别用于不同的开发场景和需求,具体使用取决于你的目标和任务。
1.2.2 引入mock.js
为了只在开发环境使用mock,而打包到生产环境时自动不使用mock,我们可以在config目录中的dev.env.js
和 prod.env.js
做一个配置,如下:
-
dev.env.js :生产环境
/* 开发环境 */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')module.exports = merge(prodEnv, {NODE_ENV: '"development"',MOCK: 'ture'
})
-
prod.env.js:开发环境
/* 生产环境 */
'use strict'
module.exports = {NODE_ENV: '"production"',MOCK: 'false'
}
-
main.js
//开发环境下才会引入mockjs
process.env.MOCK && require('@/mock')
1.3 mock.js的使用
1.3.1 准备模拟数据
为每个*.vue定义单独的xxx-mock.js文件,并在其中添加自定义的json数据,还可以通过mockjs的模块生成随机数据信息,动态测试ajax请求效果。
创建src/mock/json
目录,定义登录测试数据文件login-mock.js:
//在没有使用mock.js前,定义数据的方式(死数据)
/* const loginInfo = {code: -1,message: '密码错误'
} *///使用mockjs的模板生成随机数据
const loginInfo = {//1表示50%概率"success|1": true,//2-3指重复2到3次"msg|2-3": 'msg'
}//将当前模块导出,导出后index.js才可以导入
export default loginInfo;
面试题:js中const,var,let区别?分别写一个例子
1.变量提升:var存在变量提升,而let与const不存在变量提升,即在变量只能在声明之后使用,否在会报错。
2.重复声明:var定义的变量可以声明多次,const和let不允许重复声明变量
3.给全局添加属性:浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。
4.暂时性死区: 在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用var声明的变量不存在暂时性死区。
5.初始值设置: 在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。
6.块级作用域: 块作用域由 { }包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题:
- 内层变量可能覆盖外层变量
- 用来计数的循环变量泄露为全局变量
1.3.2 定义拦截路由
在src目录下创建mock目录,定义mock主文件index.js,并在该文件中定义拦截路由配置,/src/mock/index.js。
import Mock from 'mockjs' //引入mockjs,npm已安装
import action from '@/api/action' //引入请求地址//全局设置:设置所有ajax请求的超时时间,模拟网络传输耗时
Mock.setup({// timeout: 400 //延时400s请求到数据timeout: 200 - 400 //延时200-400s请求到数据
})//获取请求的url
let url = action.getFullPath('SYSTEM_USER_DOLOGIN');
//引登陆的测试数据,并添加至mockjs
import loginInfo from '@/mock/json/login-mock.js'
Mock.mock(url, "post", loginInfo)//如果请求既可以是get又可以是post的请求方式可以使用如下方式:
// Mock.mock(s1, /post|get/i, loginInfo)
1.3.3 测试
编辑Login.vue文件,根据不同响应,给出不同提示。
<template><div class="login-wrap"><el-form class="login-container"><h1 class="title">用户登录</h1><el-form-item label=""><el-input type="text" v-model="username" placeholder="登录账号" autocomplete="off"></el-input></el-form-item><el-form-item label=""><el-input type="password" v-model="password" placeholder="登录密码" autocomplete="off"></el-input></el-form-item><el-form-item><el-button type="warning" style="width:100%;" @click="doSubmit()">提交</el-button></el-form-item><el-row style="text-align: center;margin-top:-10px"><el-link type="primary">忘记密码</el-link><el-link type="primary" @click="gotoRegister()">用户注册</el-link></el-row></el-form></div>
</template><script>export default {name: 'Login',data() {return {username: '',password: ''}},methods: {gotoRegister() {this.$router.push("/Register");},doSubmit() {//定义后台登录方法连接地址let url = this.axios.urls.SYSTEM_USER_DOLOGIN;//获取数据let params = {username: this.username,password: this.password};/* get请求进行参数传递 */this.axios.get(url, {params: params}).then(r => {console.log(r);//提示成功和失败,主要演示获取响应数据的方法if (r.data.success) {//可以到element-ui官网查看用法this.$message({message: '登录成功',type: 'success'});}else{this.$message({message: '登录失败',type: 'error'});}}).catch(e => {//异常信息});}}}
</script><style scoped>.login-wrap {box-sizing: border-box;width: 100%;height: 100%;padding-top: 10%;background-image: url('/static/imgs/books2.jpg');/* background-color: #3b7cf5; */background-repeat: no-repeat;background-position: center right;background-size: 100%;}.login-container {border-radius: 10px;margin: 0px auto;width: 350px;padding: 30px 35px 15px 35px;border: 1px solid #eaeaea;text-align: left;background-color: rgba(229, 229, 229, 0.8);}.title {margin: 0px auto 40px auto;text-align: center;color: #0b0b0b;}
</style>
这样就不需要跟后台进行交互,通过mock.js模拟数据进行功能测试。
二、首页导航栏左侧菜单搭建
2.1 自定义界面组件 (完整代码)
1. AppMain.vue 界面总容器
<template><el-container class="main-container"><el-aside v-bind:class="asideClass"><LeftNav></LeftNav></el-aside><el-container><el-header class="main-header"><TopNav></TopNav></el-header><el-main class="main-center">首页</el-main></el-container></el-container>
</template><script>// 导入组件import TopNav from '@/components/TopNav.vue'import LeftNav from '@/components/LeftNav.vue'// 导出模块export default {//组件名称name: 'AppMain',data: function() {return {asideClass: 'main-aside',}},//将import的组件定义的Main中以便于使用components: {TopNav,LeftNav},created() {this.$root.Bus.$on('aaa', r => {this.asideClass = r ? 'main-aside-collapsed' : 'main-aside';});}};
</script>
<style scoped>.main-container {height: 100%;width: 100%;box-sizing: border-box;}.main-aside-collapsed {/* 在CSS中,通过对某一样式声明! important ,可以更改默认的CSS样式优先级规则,使该条样式属性声明具有最高优先级 */width: 64px !important;height: 100%;background-color: #e2b100;margin: 0px;}.main-aside {width: 240px !important;height: 100%;background-color: #e2b100;margin: 0px;}.main-header,.main-center {padding: 0px;border-left: 2px solid #dedede;}
</style>
2. LegtNav.vue 左侧菜单
<template><el-menu default-active="2" class="el-menu-vertical-demo" background-color="#ffbf00" text-color="#fff"active-text-color="#ffd04b" :collapse="collapsed"><div class="logobox"><img class="logoimg" src="../assets/imgs/logo.png" alt=""></div><el-submenu index="1"><template slot="title"><i class="el-icon-location"></i><span>导航一</span></template><el-menu-item-group><template slot="title">分组一</template><el-menu-item index="1-1">选项1</el-menu-item><el-menu-item index="1-2">选项2</el-menu-item></el-menu-item-group><el-menu-item-group title="分组2"><el-menu-item index="1-3">选项3</el-menu-item></el-menu-item-group><el-submenu index="1-4"><template slot="title">选项4</template><el-menu-item index="1-4-1">选项1</el-menu-item></el-submenu></el-submenu><el-menu-item index="2"><i class="el-icon-menu"></i><span slot="title">导航二</span></el-menu-item><el-menu-item index="3" disabled><i class="el-icon-document"></i><span slot="title">导航三</span></el-menu-item><el-menu-item index="4"><i class="el-icon-setting"></i><span slot="title">导航四</span></el-menu-item></el-menu>
</template>
<script>export default {name: 'LeftNav',data: function() {return {collapsed: false}},created() {this.$root.Bus.$on('aaa', r => {this.collapsed = r;});}}
</script>
<style>.el-menu-vertical-demo:not(.el-menu--collapse) {width: 240px;min-height: 400px;}.el-menu-vertical-demo:not(.el-menu--collapse) {border: none;text-align: left;}.el-menu-item-group__title {padding: 0px;}.el-menu-bg {background-color: #ffbf00 !important;}.el-menu {border: none;}.logobox {height: 40px;line-height: 40px;color: #9d9d9d;font-size: 20px;text-align: center;padding: 20px 0px;}.logoimg {height: 40px;}
</style>
3. TopNav.vue 顶部导航栏
<template><el-menu class="el-menu-demo" mode="horizontal" background-color="#ffbf00" text-color="#fff" active-text-color="#fff"><el-button class="buttonimg"><img class="showimg" :src="collapsed?imgshow:imgsq" @click="doToggle()"></el-button><el-submenu index="2" class="submenu"><template slot="title">超级管理员</template><el-menu-item index="2-1">设置</el-menu-item><el-menu-item index="2-2">个人中心</el-menu-item><el-menu-item @click="exit()" index="2-3">退出</el-menu-item></el-submenu></el-menu>
</template><script>export default {name: 'TopNav',data: function() {return {collapsed: false,//require是node中遵循CommonJS规范的模块化解决方案,支持动态引入imgshow: require('@/assets/imgs/show.png'),imgsq: require('@/assets/imgs/sq.png')}},methods: {doToggle() { //收起左侧菜单事件this.collapsed = !this.collapsed;//将是否折叠的变量放入总线this.$root.Bus.$emit('aaa', this.collapsed);},exit() { //退出事件//跳转登录界面this.$router.push("/")}}}
</script><style scoped>.el-menu-vertical-demo:not(.el-menu--collapse) {border: none;}.submenu {float: right;}.buttonimg {height: 60px;background-color: transparent;border: none;}.showimg {width: 26px;height: 26px;position: absolute;top: 17px;left: 17px;}.showimg:active {border: none;}
</style>
2.2 配置路由
router/index.js, 配置路由前先导入Main组件
import AppMain from '@/components/AppMain'
import LeftNav from '@/components/LeftNav'
import TopNav from '@/components/TopNav'
将LeftNav和TopNav子组件配置到AppMain总容器中:
export default new Router({routes: [{path: '/',name: 'Login',component: Login},{path: '/AppMain',name: 'AppMain',component: AppMain,children:[{path: '/LeftNav',name: 'LeftNav',component: LeftNav},{path: '/TopNav',name: 'TopNav',component: TopNav}]}]
})
2.3 组件显示折叠和展示图标
TopNav.vue:
LeftNav.vue:
2.4 总线完成组件通信
如果要完成组件整合,需要通过定义总线将父组件(AppMain)与子组件进行通信;
src/mai.js:
new Vue({el: '#app',data() {return {/* 创建一个Bus总线 */Bus: new Vue()}},router,components: {App},template: '<App/>'
})
TopNav.vue:
把是否折叠的变量放入总线中方便其他组件调取。
LeftNav:
在组件创建时订阅了一个名为
'aaa'
的事件,并在事件触发时将接收到的数据赋值给collapsed
属性。
AppMain.vue:
在组件创建时订阅了一个名为
'aaa'
的事件,并在事件触发时将接收到的数据赋值给asideClass
属性(通过true或false赋予相应的样式)。