博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vue-element-admin源码解读——数据Mock
阅读量:3899 次
发布时间:2019-05-23

本文共 4413 字,大约阅读时间需要 14 分钟。


MOCK是指模拟服务器按照一定的规则或者设定的数据,对客户端的请求进行响应。换个说法就是可以不用搭建后台服务器,就可以实现前端对数据的请求的响应。在vue-element-admin框架中采用的是MockJS

MockJS的原理是拦截了所有的请求并代理到本地,然后进行数据模拟,所以你会发现 network 中没有发出任何的请求。不过在vue-element-admin框架中是利用webpack-dev-serve来实现的,在你启动前端服务的同时,mock-server就会自动启动,而且这里还通过 chokidar 来观察 mock 文件夹内容的变化.在Vue.config.js中可以看到有如下配置:

devServer: {
port: port, open: true, overlay: {
warnings: false, errors: true }, //通过这一行来实现在webpack-dev-serve启动之前启动mock-server服务的 before: require('./mock/mock-server.js')},

那么就来看看mock-server.js中是如何实现的:

const chokidar = require('chokidar')const bodyParser = require('body-parser')const chalk = require('chalk')const path = require('path')const Mock = require('mockjs')//获取mock静态返回数据所在的目录const mockDir = path.join(process.cwd(), 'mock')module.exports = app => {
require('@babel/register') //添加插件 app.use(bodyParser.json()) app.use(bodyParser.urlencoded({
extended: true })) //注册数据响应路由 const mockRoutes = registerRoutes(app) var mockRoutesLength = mockRoutes.mockRoutesLength var mockStartIndex = mockRoutes.mockStartIndex //监测mock目录下的文件变化 chokidar.watch(mockDir, {
ignored: /mock-server/, ignoreInitial: true }).on('all', (event, path) => {
//一旦发生文件的变化或添加则重新添加响应路由 if (event === 'change' || event === 'add') {
try {
// remove mock routes stack app._router.stack.splice(mockStartIndex, mockRoutesLength) // 清楚路由缓存数据 unregisterRoutes() //重新注册 const mockRoutes = registerRoutes(app) mockRoutesLength = mockRoutes.mockRoutesLength mockStartIndex = mockRoutes.mockStartIndex console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${
path}`)) } catch (error) {
console.log(chalk.redBright(error)) } } })}

我们重点来看看这个响应理由是如何被注册的:

function registerRoutes(app) {
let mockLastIndex //这里就是返回的是MockXHR,即利用 const {
default: mocks } = require('./index.js') const mocksForServer = mocks.map(route => {
//重点是这里 return responseFake(route.url, route.type, route.response) }) for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response) mockLastIndex = app._router.stack.length } const mockRoutesLength = Object.keys(mocksForServer).length return {
mockRoutesLength: mockRoutesLength, mockStartIndex: mockLastIndex - mockRoutesLength }}const responseFake = (url, type, respond) => {
return {
//这里就将url上下文前缀拼接在一起 url: new RegExp(`${
process.env.VUE_APP_BASE_API}${
url}`), //默认get方法 type: type || 'get', response(req, res) {
console.log('request invoke:' + req.path) //写回json数据 // Mock.mock(templ)即返回templ数据 res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) } }}

虽然代码表面使用的是MockJs,但是实际上用的却是封装过的MockXHR,这个封装过程如下:

//import Mock from 'mockjs'import {
param2Obj } from '../src/utils'import user from './user'import role from './role'import article from './article'import search from './remote-search'//模拟数据const mocks = [ ...user, ...role, ...article, ...search]export function mockXHR() {
//这里重写了Mock的代理方法,重新定义XMLHttpRequest //这里将XHR指向了webpack-dev-serve的XHR Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send Mock.XHR.prototype.send = function() {
if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false if (this.responseType) {
this.custom.xhr.responseType = this.responseType } } this.proxy_send(...arguments) } function XHR2ExpressReqWrap(respond) {
return function(options) {
let result = null if (respond instanceof Function) {
const {
body, type, url } = options result = respond({
method: type, body: JSON.parse(body), query: param2Obj(url) }) } else {
result = respond } return Mock.mock(result) } } for (const i of mocks) {
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response)) }}export default mocks

通过重新包装MockJS之后,调用的是原生的send函数,所以在network中也可以看得见数据的传输。

Mock数据编写在了Mock目录下的userrolearticleremote-search文件中,通过上述文件统一引入mocks的数组中。

const mocks = [  ...user,  ...role,  ...article,  ...search]

然后通过遍历数组绑定在了Mock的内部映射表中。

for (const i of mocks) {
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))}

转载地址:http://lqfen.baihongyu.com/

你可能感兴趣的文章
MStar之公司简介
查看>>
STB之业务架构图
查看>>
WebKit之Port篇幅介绍
查看>>
WebKit之Binding案例(testCallback.idl)
查看>>
WebKit之binding分析案例(testInterface.idl)
查看>>
WebKit之binding案例分析(testMediaQueryListListener.idl)
查看>>
Webkit之generate-bindings.pl源码分析
查看>>
WebKit之CodeGenerate-JS的perl脚本的分析和学习
查看>>
Linux之死锁的代码体验
查看>>
WebKit之webIDL详解
查看>>
WebKit之创建Event的2种方法
查看>>
CPP之中介者设计模式
查看>>
Event的三个阶段
查看>>
WebKit之MediaPlayer的简单分析
查看>>
WebKit之MediaPlayer之底层调度的源码分析
查看>>
WIFI之系统模块列表介绍
查看>>
C++之数据库处理代理模块
查看>>
C++之编码实现ping的功能
查看>>
C++之动态配置ip信息
查看>>
生活之工资条(薪资结构参考)
查看>>