vue-element-admin源码解读——数据Mock

news/2024/7/10 0:52:18 标签: vue, nodejs
  • vue-element-admin源码解读——项目组件布局及状态管理
  • vue-element-admin源码解读——项目启动过程
  • vue-element-admin源码解读——数据Mock

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://www.niftyadmin.cn/n/1180401.html

相关文章

JQuery Easy Ui dataGrid 数据表格

2019独角兽企业重金招聘Python工程师标准>>> 数据表格 - DataGrid 内容 概况 使用方法 数据表格属性 数据列属性 编辑 数据视图 事件 方法 继承$.fn.panel.defaults,使用$.fn.datagrid.defaults重载默认值。. 数据表格显示的数据以表格的形式&#xff0c…

vue-element-admin源码解读——项目组件布局及状态管理

vue-element-admin源码解读——项目组件布局及状态管理vue-element-admin源码解读——项目启动过程vue-element-admin源码解读——数据Mock vue-element-admin作为一款优秀的前端解决方案,整个框架的结构非常清晰,同时利用Vuex和Vue Router来实现SPA(单页…

影随心动

好久没进园子了,今天看到一位叫yingsuixindong的博主的随笔,发现他从2012年开始立志写随笔后,接下来几乎每天都坚持写一篇。突然感觉自己也有写的冲动!!总得留下点痕迹不是? 转载于:https://www.cnblogs.co…

免费遥感数据下载资源

在资源生态环境方面的应用或研究,数据源可选择Landsat、资源卫星-2A(B)、环境小卫星数据、Modis数据、NOAA的AVHHR、SRTM的地形数据,这些数据基本可以免费获取。 中国资源卫星数据服务网 http://www.cresda.com 说明&#xff1…

sql server 2005修复数据库的问题

错误:SQL Server 检测到基于一致性的逻辑 I/O 错误 pageid 不正确 执行以下命令: use master declare databasename varchar(255) set databasename要恢复的数据库名称 exec sp_dboption databasename, Nsingle, Ntrue --将目标数据库置为单用户状态 dbc…

Linux 命令(四)系统监控

2019独角兽企业重金招聘Python工程师标准>>> http://os.51cto.com/art/201005/200672.htm Linux系统监控工具之vmstat详解 http://os.51cto.com/art/201005/201618.htm 十三个强大的Linux性能监测工具 转载于:https://my.oschina.net/pangzhuzhu/blog/317923

.NET的垃圾回收机制

.NET的垃圾回收机制: CLR管理内存的区域主要有三块: 一: 线程的堆栈 ,用于分配值类型实例。堆栈主要有操作系统管理,不受垃圾收集器的控制,当值类型实例所在的方法结束时,其存储单位自动释放。…

酒肆的老板娘问题

据说有人给酒肆的老板娘出了一个难题:此人明明知道店里只有两个舀酒的勺子,分别能舀7两和11两酒,却硬要老板娘卖给他2两酒,聪明的老板娘毫不含糊,用这两个勺子在酒缸里舀酒,并倒来倒去,居然量出了2两酒&…