前言
Vue CLI 3将webpack的配置融合到了自己的vue.config.js中,官方说法:https://cli.vuejs.org/zh/config/#devserver-proxy ,也就是说只要在vue.config.js中仿照webpack来配置即可。
webpack的DevServer参考文档:https://cloud.tencent.com/developer/section/1477376
我们打算实现:
- 正常的路由,就由vue cli来管理。
- ajax请求的路由,因为这个路由我们希望拿到模拟数据,所以不归vue cli管,而是由webpack的DevServer来拦截。拦截之后,我们要提前安装一个package叫mockjs,由它来生成模拟数据,然后返回模拟数据。
原理
- 利用webpack的DevServer实现一个本地服务器,这个服务器跟Vue CLI默认生成的服务器使用同一个IP和端口,也就是要同源,这样问题最简单,不用考虑代理。
- 准备一个mock/mock.js负责编写规则。
- DevServer的before中拦截所有请求,交给Mock。其实拦截所有请求不是最佳实践,应该根据请求内容拦截,但是今天我们只把问题最简单化,所以拦截所有请求,交给Mock。
- Mock返回模拟数据,这样我们编写的请求代码,得到的就是模拟数据了。
DevServer配置本地服务器
在项目根目录,也就是跟package.json平级,新建一个mock目录,内容一会再说。
在vue.config.js中加入:
const path = require('path');
const Mock = require('./mock/mock.js');
devServer: {
contentBase: path.join(__dirname, 'mock'),
compress: true,
port: 8080,
overlay: {
warnings: false,
errors: true
},
before(app){
Mock(app)
}
}
DevServer的配置中有一个before
配置项,意思是拦截路由请求。我们现在简单粗暴的拦截所有请求,全部交给Mock(app)
处理。
app
是什么呢,它是一个很复杂的对象,暂时没必要了解它具体是什么,你只需要知道,app.get()
就等同于axios.get()
就行了,也就是app的一些方法会映射到axios上。
注意,修改webpack的配置之后,需要重新运行
yarn serve
!否则不生效!后续有修改如果也不生效的话,重新运行yarn serve
一般就没问题了。
如果你有能力,可以使用https://github.com/paulmillr/chokidar来监听目录文件变化,然后自动重启服务器。这里我就不介绍了。
在mock目录新建一个mock.js
- 我们先写它的基础内容,比如说,我请求购物车的商品列表,那么可以是:
function Mock(app) {
app.get('/cart/getCartList', function(req, res) {
res.json({ aaa: '111' });
});
}
module.exports = Mock;
其中'/cart/getCartList'
是真的路径,而{ aaa: '111' }
是我mock出的数据。
在src/api/目录新建一个cart.js
这个操作是Vue CLI项目的业界惯例的操作,也就是将ajax请求写成模块,比如内容是:
import $httpJava from '@/assets/js/httpJava.js'; // 我封装的axios实例
const devBaseURL = 'http://192.168.2.142:8080'; // 因为经常要切换baseURL,所以另外定义一个变量
export function getCartList() {
return $httpJava({
baseURL: devBaseURL,
url: '/cart/getCartList',
method: 'get'
})
}
在组件中调用你的ajax模块
比如在Cart.vue中:
import { getCartList } from '@/api/cart'
create() {
methods: {
getCartList()
}
}
打开浏览器的Network,可以看到:
到此,如果你的模拟数据够简单的话,看到这里就不用再看下去了。如果你的模拟数据很庞大,很复杂,需要随机数据,需要各种计算数据,那么显然返回一个JSON对象是不能满足需求了。怎么办?——Mockjs该登场了。
安装Mockjs
yarn add mockjs --dev
官方文档:https://github.com/nuysoft/Mock/wiki/Getting-Started
先来一个例子。
首先先把/mock/mock.js做模块化处理:
mock.js:
const cartMock = require('./cart');
function Mock(app) {
cartMock(app)
}
module.exports = Mock;
旁边新建cart.js:
var Mockjs = require('mockjs')
const cartMock = function (app) {
app.get('/cart/getCartList', function(req, res) {
var data = Mockjs.mock({
// 属性 list 的值是一个数组,其中元素的数量从 1 到 10 个都有可能,随机
'list|1-10': [{
// 属性 id 是一个自增数,起始值为 5,每次增 1
'id|+1': 5
}]
})
res.json(data);
})
}
module.exports = cartMock;
得到:
现在我们构建一个复杂的模拟数据数组:
var Mockjs = require('mockjs')
var Random = Mockjs.Random
const cartMock = function (app) {
app.get('/cart/getCartList', function(req, res) {
var goods_id = 1
var data = Mockjs.mock({
'list|3-5': [{
'merchant_id|+1': 50,
'merchant_name': Random.cword( '阿福水果苹果梨哈密瓜桃杏', 2, 3 ) + '旗舰店',
'goodsList|2-4': [{
'goods_id': goods_id++,
'goods_img': 'https://img.yzcdn.cn/upload_files/2014/11/29/FjKSRZNOLrncW19bpyfLu3hrtNPe.jpg?imageView2/2/w/260/h/260/q/75/format/jpg',
'goods_title': '四川红心猕猴桃 新鲜当季水果奇异果应季猕猴桃孕妇批发五只装精品豪华装',
'goods_price': '@float( 11, 44, 0, 2 ),
'good_quantity': Random.natural( 1, 4 )
}]
}]
})
res.json(data);
})
}
module.exports = cartMock;
如果仔细看你会看到,'goods_id': goods_id++,
在每一个元素中随机出的结果是一样的,都是1,Random的结果也都是一样的,如果要避免这种现象,可以使用@natural
这种占位符加参数。
总而言之,你就是攒出一个JS对象,传给Mockjs.mock()就完事。如果看不懂,请仔细阅读手册。
拿到response之后再怎么用,就不说了。