1.Mock.js
1. Mock.js란 무엇인가요?
Mock.js는 모의 데이터를 생성하기 위한 JavaScript 라이브러리입니다. 백엔드 API 인터페이스를 시뮬레이션하고 프런트엔드 개발 중에 인터페이스 디버깅 및 테스트에 사용되어 자동화된 테스트의 효율성을 향상시킬 수 있습니다. Mock.js를 사용하면 가상 데이터를 빠르게 생성하고 데이터 유형, 형식 및 규칙을 설정하여 실제 데이터 응답을 시뮬레이션할 수 있습니다. Mock.js는 무작위 데이터 생성, Ajax 요청을 가로채서 시뮬레이션된 데이터 반환, RESTful API 스타일 지원과 같은 기능을 지원하며 프런트엔드 개발 효율성을 향상시키고 백엔드 인터페이스에 대한 의존도를 줄일 수 있습니다.
풍부한 데이터 유형: 임의의 텍스트, 숫자, 부울 값, 날짜, 이메일, 링크, 사진, 색상 등 생성을 지원합니다.
Ajax 요청 차단: 기존 코드를 수정하지 않고도 Ajax 요청을 차단하고 시뮬레이션된 응답 데이터를 반환할 수 있습니다.
자세한 내용은 Mock.js 공식 홈페이지를 확인해주세요.
2. 설치 및 구성
1. 설치
프로젝트 경로의 CMD 창에서 Mock.js를 다운로드하세요.
npm i mockjs -D
-D는 개발 환경에서만 사용함을 의미합니다.
package.json 에서 다운로드한 mock.js를 볼 수 있습니다.
2. 소개
개발 환경에서는 모의 객체 만 사용 하고 프로덕션 환경으로 패키징할 때는 자동으로 모의 객체를 사용하지 않으 려면 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: 'true'
})
prod.env.js
'use strict'
module.exports = {
NODE_ENV: '"production"',
MOCK: 'false'
}
마지막으로 main.js로 가져옵니다.
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
//开发环境下才会引入mockjs
process.env.MOCK && require('@/mock')
// 新添加1
import ElementUI from 'element-ui'
// 新添加2,避免后期打包样式不同,要放在import App from './App';之前
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
import router from './router'
// 新添加3----实例进行一个挂载
Vue.use(ElementUI)
Vue.config.productionTip = false
import axios from '@/api/http'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: {App},
template: '<App/>'
})
2. Mock.js 사용
1. 테스트 데이터 파일 정의
각 *.vue에 대해 별도의 xxx-mock.js 파일을 정의하고 여기에 사용자 정의 json 데이터를 추가합니다. 또한 mockjs 모듈을 통해 임의의 데이터 정보를 생성하여 ajax 요청 효과를 동적으로 테스트 할 수도 있습니다 .
src/mock/json 디렉터리를 만들고 로그인 테스트 데이터 파일 login-mock.js를 정의합니다 .
// const loginInfo = { // code: -1, // message: '密码错误' // } //使用mockjs的模板生成随机数据 const loginInfo = { 'code|-1-0': 0, 'message|3-10': 'msg' } export default loginInfo;
2. 모의가 Ajax 요청을 가로챕니다.
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请求到数据 }) //引登陆的测试数据,并添加至mockjs import loginInfo from '@/mock/json/login-mock.js' let s1 = action.getFullPath('SYSTEM_USER_DOLOGIN') Mock.mock(s1, "post", loginInfo) // Mock.mock(s1, /post|get/i, loginInfo)
3. 시뮬레이션 테스트
로그인 페이지 모의 테스트 사용
<template> <div class="Login"> <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="primary" 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; // 使用json格式进行传值 let params = { username: this.username, password: this.password } this.axios.post(url, params).then(r => { console.log(r); this.$message({ message: r.data.message, type: r.data.code == 0?'success': 'error' }); }).catch(e => { }); } } } </script> <style scoped> .login-wrap { box-sizing: border-box; width: 100%; height: 100%; padding-top: 10%; background-image: url(https://pic4.zhimg.com/v2-c5880f5a6d44766feb085c3ae94899c7_r.jpg); //background-image: url(); 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; background: #fff; border: 1px solid #eaeaea; text-align: left; box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1); } .title { margin: 0px auto 40px auto; text-align: center; color: #505458; } </style>
2. 홈페이지 탐색 및 왼쪽 메뉴
1. 페이지 구성
우리 컴포넌트 의 public 폴더에 공개 페이지를 작성하세요 .
AppMain.vue: 레이아웃 컨테이너 구성 요소
LeftAside.vue: 왼쪽 메뉴 구성 요소
TopNav.vue: 홈 페이지 탐색 구성 요소는
vue 구성 요소 간에 전달되는 데이터를 기반으로 element-ui의 NavMenu 메뉴 접기 및 펼치기 효과를 실현합니다.하위 구성 요소는 상위 구성 요소인 TopNav -> AppMain에 데이터(this.$emit)를 전달하고, 상위
구성 요소는 하위 구성 요소인 AppMain -> LeftAside에 데이터(props)를 전달합니다.
1.1 아이콘 정의
아이콘은 자신의 스타일에 따라 사용자 정의할 수 있습니다. 아래에 제공했으며 직접 변경할 수도 있습니다.
1.2, 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 {
};
</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: #334157;
margin: 0px;
}
.main-aside {
width: 240px !important;
height: 100%;
background-color: #334157;
margin: 0px;
}
.main-header,
.main-center {
padding: 0px;
border-left: 2px solid #333;
}
</style>
1.3, 왼쪽Nav.vue
<template>
<el-menu default-active="2" class="el-menu-vertical-demo" background-color="#334157"
text-color="#fff" active-text-color="#ffd04b" :collapse="collapsed">
<div class="logobox">
<img class="logoimg" src="../assets/img/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 {
}
</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: #1f2d3d !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>
1.4, TopNav.vue
<template>
<el-menu class="el-menu-demo" mode="horizontal" background-color="#334157" 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 {
data() {
return {
collapsed: false,
imgshow: require('@/assets/img/show.png'),
imgsq: require('@/assets/img/sq.png')
}
}, methods: {
}
}
</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>
1.5、index.js
index 및 js에서 라우팅 구성 수행
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import Login from '@/views/Login' import Register from '@/views/Register' import AppMain from '@/components/AppMain' import LeftNav from '@/components/LeftNav' import TopNav from '@/components/TopNav' Vue.use(Router) export default new Router({ routes: [ { path: '/Login', name: 'Login', component: Login }, { path: '/Register', name: 'Register', component: Register }, { path: '/AppMain', name: 'AppMain', component: AppMain, children: [{ path: '/LeftNav', name: 'LeftNav', component: LeftNav }, { path: '/TopNav', name: 'TopNav', component: TopNav }] } ] })
2. 기능 구현
2.1, AppMain.vue
// 导出模块
export default {
//把顶部导航和左边导航进行绑定在main
components: {
TopNav, LeftNav
},
data() {
return {
asideClass: 'main-aside'
}
},
created() {
this.$root.Bus.$on('sjm', v => {
this.asideClass = v ? 'main-aside-collapsed' : 'main-aside';
});
}
};
2.2, 왼쪽Nav.vue
export default {
data() {
return {
collapsed: false
}
},
created() {
this.$root.Bus.$on('sjm', v => {
this.collapsed = v;
});
}
}
2.3, TopNav.vue
export default {
data() {
return {
collapsed: false,
imgshow: require('@/assets/img/show.png'),
imgsq: require('@/assets/img/sq.png')
}
}, methods: {
//图标的切换
doToggle() {
this.collapsed = !this.collapsed;
//定义一个事件名,将是否折叠变量放入总线
this.$root.Bus.$emit('sjm', this.collapsed)
},
exit() {
this.$router.push('/Login');
}
}
}
2.4、main.js
data() {
return {
Bus: new Vue()
}
}
3. 완전한 코드
3.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 {
//把顶部导航和左边导航进行绑定在main
components: {
TopNav, LeftNav
},
data() {
return {
asideClass: 'main-aside'
}
},
created() {
this.$root.Bus.$on('sjm', v => {
this.asideClass = v ? '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: #334157;
margin: 0px;
}
.main-aside {
width: 240px !important;
height: 100%;
background-color: #334157;
margin: 0px;
}
.main-header,
.main-center {
padding: 0px;
border-left: 2px solid #333;
}
</style>
3.2, 왼쪽Nav.vue
<template>
<el-menu default-active="2" class="el-menu-vertical-demo" background-color="#334157"
text-color="#fff" active-text-color="#ffd04b" :collapse="collapsed">
<div class="logobox">
<img class="logoimg" src="../assets/img/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 {
data() {
return {
collapsed: false
}
},
created() {
this.$root.Bus.$on('sjm', v => {
this.collapsed = v;
});
}
}
</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: #1f2d3d !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.3, TopNav.vue
<template>
<el-menu class="el-menu-demo" mode="horizontal" background-color="#334157" 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 {
data() {
return {
collapsed: false,
imgshow: require('@/assets/img/show.png'),
imgsq: require('@/assets/img/sq.png')
}
}, methods: {
//图标的切换
doToggle() {
this.collapsed = !this.collapsed;
//定义一个事件名,将是否折叠变量放入总线
this.$root.Bus.$emit('sjm', this.collapsed)
},
exit() {
this.$router.push('/Login');
}
}
}
</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>
3.4、main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
//开发环境下才会引入mockjs
process.env.MOCK && require('@/mock')
// 新添加1
import ElementUI from 'element-ui'
// 新添加2,避免后期打包样式不同,要放在import App from './App';之前
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
import router from './router'
// 新添加3----实例进行一个挂载
Vue.use(ElementUI)
Vue.config.productionTip = false
import axios from '@/api/http'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
//定义变量
data() {
return {
Bus: new Vue()
}
},
components: {App},
template: '<App/>'
})