vue mock 模拟后端api接口

举报
福州司马懿 发表于 2021/11/19 00:51:32 2021/11/19
【摘要】 模拟ajax响应 安装插件 axios 是对 ajax 请求的封装 对于 ajax 请求,使用 mockjs 插件来模拟后端响应 npm install axios --save npm insta...

模拟ajax响应

安装插件

axios 是对 ajax 请求的封装
对于 ajax 请求,使用 mockjs 插件来模拟后端响应

npm install axios --save
npm install mockjs --save-dev

  
 
  • 1
  • 2

配置环境

修改 config/dev.env.js,添加 MOCK 变量,值为 true

'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  MOCK: 'true'
})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

修改 config/prod.env.js,添加 MOCK 变量,值为 false

'use strict'
module.exports = {
  NODE_ENV: '"production"',
  MOCK: 'false'
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

绑定全局

src/main.js 文件中,将 axios 组件绑定到 Vue 上,并且配置只有在 debug 模式,即 npm run dev 的情况下,才引入 Mock

import axios from 'axios'
process.env.MOCK && require('@/mock')

Vue.prototype.$http = axios

  
 
  • 1
  • 2
  • 3
  • 4

杜撰 Mock 数据

import Mock from 'mockjs'

const Random = Mock.Random
const GET = 'get'
// const POSt = 'POST'
const msg = '成功'
let articles = []
for (let i = 0; i < 10; i++) {
  let article = {
    id: Random.id(),
    title: Random.csentence(10, 20),
    icon: Random.dataImage('100x100', 'Article Icon'),
    author: Random.cname(),
    date: Random.date() + ' ' + Random.time()
  }
  articles.push(article)
}

// 设置请求延时时间
Mock.setup({
  timeout: 1000,
  debug: false
})

Mock.mock(/test/, GET, (req) => {
  return {
    code: 0,
    msg
  }
})

// mockjs暂不支持获取路径变量,因此只能自己提取
// 该函数可以实现获取所有文章(article),或根据id获取单条文章(article/:id)两种接口
Mock.mock(/article/, GET, (req) => {
  const path = 'article'
  const url = req.url
  const index = url.lastIndexOf(path) + path.length + 1
  if (index < url.length) {
    const id = url.substring(index)
    const filterData = articles.filter(item => { return item.id === id })
    if (filterData.length > 0) {
      return {
        code: 0,
        msg,
        data: filterData[0]
      }
    } else {
      return {
        code: -1,
        msg: '文章不存在'
      }
    }
  } else {
    return {
      code: 0,
      msg,
      data: articles
    }
  }
})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

请求方法

在 App.vue 中添加具体请求方法

注意:'err' is declared but its value is never read.,err已被全局定义,且是只读的,所以必须换个名字

<script>
export default {
  name: 'App',
  mounted: function () {
    this.getArticle1()
    this.getArticle2()
    console.log('http request finish')
  },
  methods: {
    getArticle1 () {
      this.$http.get('/article').then(res => {
        console.log('axios article', res.data)
      }).catch(_err => {
        console.log('axios err', _err)
      })
    },
    getTest1 () {
      this.$http.get('/test').then(res => {
        console.log(res.data)
      }).catch(_err => {
        console.log('axios err', _err)
      })
    },
    getArticle2 () {
      this.$fetch.get('./article').then(res => {
        console.log('fetch article', res)
      }).catch(_err => {
        console.log('axios err', _err)
      })
    },
    getTest2 () {
      this.$fetch.get('./test').then(res => {
        console.log('fetch test', res)
      }).catch(_err => {
        console.log('axios err', _err)
      })
    }
  }
}
</script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

输出结果

在这里插入图片描述

模拟fetch响应

安装插件

由于 mockjs 只能模拟 ajax 请求,而对fetch请求无法拦截修改,因此需要 额外引入 mockjs-fetch 插件,对 mock 对象进行改造

npm install mockjs --save-dev
npm install mockjs-fetch --save

  
 
  • 1
  • 2

封装工具

首先对于fetch做一个简单的封装 src/utls/myFetch.js

let baseUrl = ''

/**
 * 设置基础url
 * @param {string} url 基础baseUrl
 */
function setBaseUrl (url) {
  baseUrl = url
}

/**
 * 对象转字符串
 * @param {object} obj 参数对象
 */
function obj2Str (obj) {
  // let idx = 0
  // let arr = []
  // for (let item in obj) {
  //   arr[idx++] = [item, obj[item]]
  // }
  // return new URLSearchParams(arr).toString()
  return Object.keys(obj).map(it => it + '=' + obj[it]).join('&')
}

/**
   * 真正的请求
   * @param {string} url 请求地址
   * @param {object} options 请求参数
   * @param {string} method 请求方式
   */
function doFetch (url, options = {}, method = 'GET') {
  url = baseUrl + url // 如果设置过基础地址,要先进行拼接
  method = method.toUpperCase() // 统一转成大写,方便后续判断
  const searchStr = obj2Str(options)
  let initObj = {}
  if (method === 'GET') {
    if (searchStr.length > 0) url = url + '?' + searchStr
    initObj = {
      method: method,
      credentials: 'include' // 强制加入凭据头
    }
  } else {
    initObj = {
      method: method,
      credentials: 'include', // 强制加入凭据头
      headers: new Headers({
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      }),
      mode: 'cors', // 以CORS的形式跨域
      cache: 'force-cache',
      body: searchStr
    }
  }
  return new Promise((resolve, reject) => {
    fetch(url, initObj).then((res) => {
      return res.json()
    }).then(res => {
      resolve(res)
    }).catch(err => {
      reject(err)
    })
  })
}

/**
   * GET 请求
   * @param {string} url 请求地址
   * @param {object} options 请求参数
   */
function get (url, options) {
  return doFetch(url, options, 'GET')
}

/**
   * POST 请求
   * @param {string} url 请求地址
   * @param {object} options 请求参数
   */
function post (url, options) {
  return doFetch(url, options, 'POST')
}

function test () {
  alert('ok')
}

export default {
  test,
  setBaseUrl,
  get,
  post
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

修改Mock数据类

修改 src/mock/index.js 文件,使用 Mock 类初始化 mockFetch 工具类,从而修改系统原始的 Fetch 方法

import Mock from 'mockjs'
import mockFetch from 'mockjs-fetch'
mockFetch(Mock)

  
 
  • 1
  • 2
  • 3

全局绑定 fetch 工具类

修改 src/main.js,使用 mockjs-fetch 插件,对 mockjs 进行封装,并全局绑定对 fetch 封装的工具类

import myfetch from './utils/myFetch'
process.env.MOCK && require('@/mock')
Vue.prototype.$fetch = myfetch

  
 
  • 1
  • 2
  • 3

其余均与之前一致

特别注意

fetch 的 method 用的是大写,而 ajax(axios) 的 method 用的是小写,因此官方插件不能同时生效

若要同时生效,可以修改 node_modules/mockjs-fetch/index.js ,将 options.method 和 item.rtype 全部转为小写

(略)
window.fetch = function(url, options) {
        options = options || {method: 'GET'};
        //添加上这一句,将method转为小写,可以使得axios与fetch并存
        options.method = options.method.toLowerCase();
        const method = options.method;
        if (Mock.XHR._settings.debug) {
            console.log(`${method} ${url}`, 'options: ', options);
        }
        for (const key in Mock._mocked) {
            const item = Mock._mocked[key];
            const urlMatch = (typeof item.rurl === 'string' && url.indexOf(item.rurl) >= 0) ||
                (item.rurl instanceof RegExp && item.rurl.test(url));
            //同时,这里也将item.rtype转为小写
            const methodMatch = !item.rtype || (item.rtype.toLowerCase() === method);
            if (urlMatch && methodMatch) {
(略)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

文章来源: blog.csdn.net,作者:福州-司马懿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/chy555chy/article/details/113804955

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。