介绍
Mock.js的特点:
1,前后端分离
让前端攻城师独立于后端进行开发。增加单元测试的真实性,通过随机数据,模拟各种场景。
2,开发无侵入
不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据。
3,数据类型丰富
支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜色等。
4,方便扩展
支持支持扩展更多数据类型,支持自定义函数和正则。
简单的来说通过Mock.js我们就可以自己模拟数据和请求,而不通过后台来完成了。
使前后端分离。
要想使用Mock.js,首先第一步是安装Mockjs依赖,
在项目cmd中输入:
npm install mockjs -D #只在开发环境使用
即可下载。
下载完后在项目中引入:
在config文件夹中的dev.env添加MOCK: ‘true’,prod.env 文件中添加MOCK: ‘false’
dev.env
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
MOCK: 'true'
})
prod.env
module.exports = {
NODE_ENV: '"production"',
MOCK: 'false'
}
然后在根目录下的main.js中添加
process.env.MOCK && require('@/mock')
这样的配置是为了只在开发环境使用mock,而打包到生产环境时自动不使用mock。
若不想用测试数据 写要请求后台了,则在main.js‘把 process.env.MOCK && require(’@/mock’)删除即可。
测试
首先导入我写的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, "get", loginInfo)
// Mock.mock(s1, /post|get/i, loginInfo)
json文件夹:
login-mock.js:
//使用mockjs的模板生成随机数据
const loginInfo = {
'code|0-1': 0,
'msg|3-10': 'msg'
}
export default loginInfo;
还有api文件夹中的:
action.js:
/**
* 对后台请求的地址的封装,URL格式如下:
* 模块名_实体名_操作
*/
export default {
'SERVER': 'http://localhost:8080/SSH', //服务器
'SYSTEM_USER_DOLOGIN': '/vue/userAction_login.action', //用户登陆
'SYSTEM_USER_DOREG': '/vue/userAction_reg.action', //用户注册
'SYSTEM_MENU_TREE': '/vue/treeNodeAction.action', //左侧树形菜单加载
'SYSTEM_ARTICLE_LIST': '/vue/articleAction_list.action', //文章列表
'SYSTEM_ARTICLE_ADD': '/vue/articleAction_add.action', //文章新增
'SYSTEM_ARTICLE_EDIT': '/vue/articleAction_edit.action', //文章修改
'SYSTEM_ARTICLE_DEL': '/vue/articleAction_del.action', //文章删除
'SYSTEM_USER_GETASYNCDATA': '/vue/userAction_getAsyncData.action', //vuex中的异步加载数据
'getFullPath': k => { //获得请求的完整地址,用于mockjs测试时使用
return this.SERVER + this[k];
}
}
这三个文件,主要的是index.js
他第一步是获取拦截地址:
通过 action李的getFullPath方法获得拦截地址,
let s1 = action.getFullPath('SYSTEM_USER_DOLOGIN')
然后建立一个Mock:
Mock.mock(s1, "get", loginInfo)
Mock.mock(url, type, data).
参数名 | 参数需求 | 参数描述 | 例子 |
---|---|---|---|
url | 可选: URL 字符串或 URL 正则 | 拦截请求的地址 | s1 |
type | 可选 | 拦截Ajax类型 | GET、POST |
template | 可选:可以是对象或字符串 | 生成数据的模板 | loginInfo |
template可能有些难理解,其实就是模拟返回数据的类型,参数。
就比如我login-mock.js这个文件:
const loginInfo = {
'code|0-1': 0,
'msg|3-10': 'msg'
}
参数名|返回次数:数据类型或者内容
这里代表的是,返回的数据中有code和msg,
code返回的是数字0-1之间,
msg返回的是msg3-10次。
例:
doLogin() {
let url = this.axios.urls.SYSTEM_USER_DOLOGIN;
console.log(url)
this.axios.get(url, { //注意数据是保存到json对象的params属性
params: this.ruleForm
//then相当于成功回调函数
}).then((response) => {
console.log(response);
if (response.data.code == 1) {
this.$message({
showClose: true,
message: response.data.msg,
type: 'success'
});
this.$router.push({
path:'/AppMain'
})
} else {
this.$message({
showClose: true,
message: response.data.msg,
type: 'error'
});
}
}).catch((response) => {
//carch则是异常
console.log(response);
});
}
效果:
里面的数据都是随机生成的,code可能等于1也可能等于0msg可能产生3次-10次。
跳转
使用this.$router.push({})实现路由跳转。
在Spa项目中跳转参数分为:
1 字符串 this.$router.push(’/home/first’)
2 对象 this.$router.push({ path: ‘/home/first’ })
3 命名的路由 this.$router.push({ name: ‘home’, params: { userId: wise }})
跳转方式:
this.$router.push()
跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面
this.$router.replace()
同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。
this.$router.go(n)
相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。负数返回上一个页面。
vue Bus总线
意思就是将一个空的Vue实例放到根组件下,所有的子组件都能调用。这样的好处就是所有的组件都能调用这个参数,
首先在main.js 里的newVue data()中,添加Bus:new Vue({ }):
new Vue({
el: '#app',
data(){
return{
Bus:new Vue({
})
}
},
router,
components: { App },
template: '<App/>'
})
在A组件触发事件
this.
r
o
o
t
.
B
u
s
.
root.Bus.
root.Bus.emit(“事件名”, 参数1, 参数2, …);
A组件中第一个是事件名,第二个之后则都是参数,
例:
this.$root.aa.$emit('collapsed-side','aa')
在B组件监听事件
this.
r
o
o
t
.
B
u
s
.
root.Bus.
root.Bus.on(“事件名”, 回调函数);
B组件中,事件名要与触发事件中的保持一致,回调函数则是你要改变的内容,v可能代表参数,
例:
created(){
this.$root.aa.$on('collapsed-side',(v)=>{
this.collapsed = v;
});
}
需要注意的是
有时候会发生事件只被emit触发了一次,但是回调函数却被执行了多次的现象。这种现象往往发生在页面跳转退出后重新进入的时候。
产生原因:
this.
r
o
o
t
.
B
u
s
.
root.Bus.
root.Bus.on实际是向Bus容器中添加一个事件监听器,当页面跳转时,原来的vue组件被注销,但是原来vue组件向Bus容器中添加的事件监听器并不会被移除。
因此,当下次进入这个vue组件对应的页面时,执行到this.
r
o
o
t
.
B
u
s
.
root.Bus.
root.Bus.on时,又会向Bus容器中添加一个重复的事件监听器,以此类推,
导致Bus容器中有很多个一模一样的事件监听器,从而导致事件只被触发一次,但是回调函数被执行多次的现象。
解决方案:
在vue组件的beforeDetory钩子函数中将本vue组件往Bus容器中添加的事件监听器全部手动移除。
//在vue对象的methods域中定义个函数专门移除事件监听器
offxxxListener: function () {
this.$root.Bus.off("事件名");
this.$root.Bus.off("事件名");
this.$root.Bus.off("事件名");
},
//在vue对象的beforeDestroy钩子中调用以上函数
beforeDestroy() {
this.offxxxListener();
},