mockJS实现拦截,是模拟了XMLHttpRequest对象。重写open、send等方法,方法调用时,只是普通函数的调用,不会发送真正的请求。
MockJS使用
- 引入mockjs
<script src="https://cdn.bootcdn.net/ajax/libs/Mock.js/1.0.1-beta3/mock.js"></script>
- 拦截匹配 url 的 Ajax 请求,根据数据模板生成模拟数据,并作为响应数据返回。
Mock.mock('mock/news', 'GET', {
'list|1-10': [{
'id|+1': 1,
'name': "@cname"
}]
})
- 请求 url,获得模拟数据
axios.get('mock/news').then(res => {
console.log(res) // res为json格式的模拟数据
})
Ajax拦截原理
- 覆盖原生 XMLHttpRequest
- ajax请求会创建XMLHttpRequest对象,覆盖原生XMLHttpRequest,ajax请求时,就会调用我们写的函数了
(源码:/src/mock.js)
MockXMLHttpRequest = require('./mock/xhr')
Mock.mock = function(rurl, rtype, template) {
...
if (XHR) window.XMLHttpRequest = MockXMLHttpRequest
...
}
如上,调用Mock.mock方法的时候,会执行 window.XMLHttpRequest = MockXMLHttpRequest,覆盖原生 XMLHttpRequest。
下面来看 MockXMLHttpRequest构造函数
- 模拟原生 XMLHttpRequest
(源码:/mock/xhr/xhr.js)
function MockXMLHttpRequest() {
// 初始化 custom 对象,用于存储自定义属性
this.custom = {
events: {},
requestHeaders: {},
responseHeaders: {}
}
}
Util.extend(MockXMLHttpRequest.prototype, {
open: function(method, url, async, username, password) {
var that = this
Util.extend(this.custom, {
method: method,
url: url,
async: typeof async === 'boolean' ? async : true,
username: username,
password: password,
options: {
url: url,
type: method
}
})
......
},
timeout: 0,
withCredentials: false,
upload: {},
send: function send(data) {
var that = this
this.custom.options.body = data
......
that.response = that.responseText = JSON.stringify(
convert(that.custom.template, that.custom.options),//根据数据模板生成json模拟数据
null, 4
)
},
abort: function abort() {
// 拦截 XHR
this.readyState = MockXMLHttpRequest.UNSENT
this.dispatchEvent(new Event('abort', false, false, this))
this.dispatchEvent(new Event('error', false, false, this))
}
})
上面是部分删减源码,摆出来只是为了表达:open、send、abort等函数,或者属性也好,都是自己写出来的普通函数和属性。
比如open函数,主要就是把method和url保存到变量中。send函数,把生成的模拟数据赋值给response和responseText
这样,响应数据就是用户设置的模拟数据。
ajax请求发生时,请求根本没有发出,只是调用了几个自己写的普通函数,得到了返回数据而已。