hbuild uniapp mock 模拟数据


小程序  app 不支持mockjs拦截  h5 可以

本文通过匹配url  返回json数据  json可以mock

uni.request promise插件  通用轻量级api接口网络请求(支持拦截器) - DCloud 插件市场

建目录mock 

对url 进行匹配,调用相应的方法返回json数据,支持路径参数 pathvariable 如 get baidu.com/:id。 若未匹配到则走网络请求

mockRequest.js 

/**

  • version 1.0.0

*/

class MockRequest {
constructor(config = {}) {

  // {url,fun}
  this.urlListener = [];
  this.request = {}
this.config = {};
this.config.baseUrl = config.baseUrl? config.baseUrl: '';
this.config.dataType = config.dataType? config.dataType: 'json';
this.config.responseType = config.responseType? config.responseType: 'text';
this.config.header = config.header? config.header: {};
this.reqInterceptors = null;
this.resInterceptors = null;
this.interceptors = {
  request: fn => {
    this.reqInterceptors = fn;
  },
  response: fn => {
    this.resInterceptors = fn;
  }
}

}
async get(url, config = {}) {

return this._request('get', url, config);

}
async post(url, config = {}) {

return this._request('post', url, config);

}
async put(url, config = {}) {

return this._request('put', url, config);

}
async delete(url, config = {}) {

return this._request('delete', url, config);

}
/**

  • 注册url
  • @param {Object} url 访问对象
  • @param {Object} fun 绑定的方法

*/
registUrl(url,fun){

  this.urlListener.push({url,fun})

}

setConfig(config = {}) {

this.config = this._deepCopy(this._merge(this.config, config));

}
getConfig() {

return this.config;

}

setRequest(request = {}) {

this.request = request;

}
getRequest() {

return this.request;

}

_request(method, url, config) {

  // 匹配url
  let reqUrl = method+" "+url;
  if(reqUrl.indexOf("?")!=-1){
      reqUrl = reqUrl.substr(0,reqUrl.indexOf("?"));
  }
  let matchUrl;
  let matchFun;
    console.log('mock url: '+url,this.urlListener);
  for (var i = 0; i < this.urlListener.length; i++) {
      let urlStr = this.urlListener[i].url
    if(!urlStr.startsWith(method)){
        continue;
    }
    // 匹配路径变量 只能匹配一个 如: "get baidu.com/:id"  "get baidu.com/:id/ab"
    if(urlStr.indexOf(":")!=-1){
        let pathVar = urlStr.match(/:\w+/);
        let urlReg = urlStr.replace(pathVar,"\\w+");
        let matchStr = reqUrl.match(urlReg);
        if(matchStr){
            matchUrl = urlStr;
            matchFun = this.urlListener[i].fun;
        }
    }else if(urlStr===reqUrl){
        matchUrl = urlStr;
        matchFun = this.urlListener[i].fun;
    }
  }
  console.log('mock request url:  '+matchUrl+' ==> '+method +' '+url)
  if(matchFun){
      //模拟异步请求数据
      return new Promise(resolve=>{
          setTimeout(()=>{
            let data = matchFun.call(method,url,config);
              resolve(data);
          }, 500)
      })
  }else{
      if(this.request && this.request._request){
          this.request._request(method,url,config);
      }else{
          console.log('non request send.')
      }
  }

}
_formatUrl(baseUrl, url) {

if (!baseUrl) return url;
let formatUrl = '';
const baseUrlEndsWithSlash = baseUrl.endsWith('/');
const urlStartsWithSlash = url.startsWith('/');
if (baseUrlEndsWithSlash && urlStartsWithSlash) {
  formatUrl = baseUrl + url.substring(1);
} else if (baseUrlEndsWithSlash || urlStartsWithSlash) {
  formatUrl = baseUrl + url;
} else {
  formatUrl = baseUrl + '/' + url;
}
return formatUrl;

}
_merge(oldConfig, newConfig) {

let mergeConfig = this._deepCopy(oldConfig);
if (!newConfig || !Object.keys(newConfig).length) return mergeConfig;
for (let key in newConfig) {
  if (key !== 'header') {
    mergeConfig[key] = newConfig[key];
  } else {
    if (Object.prototype.toString.call(newConfig[key]) === '[object Object]') {
      for (let headerKey in newConfig[key]) {
        mergeConfig[key][headerKey] = newConfig[key][headerKey];
      }          
    }
  }
}
return mergeConfig;

}
_deepCopy(obj) {

let result = Array.isArray(obj) ? [] : {};
for (let key in obj) {
  if (obj.hasOwnProperty(key)) {
    if (typeof obj[key] === 'object') {
      result[key] = this._deepCopy(obj[key]);
    } else {
      result[key] = obj[key];
    }
  }
}
return result;

}
}

if (!global.$mockRequest) {
global.$mockRequest = new MockRequest();
}

export default global.$mockRequest;

userMock.js

模块mock   指定 url  function 

function getUserInfo(method,url,config){

let data = {"success":true};
return JSON.stringify(data)

}

export default {

'get /userInfo': getUserInfo

}
index.js

加载各个模块的mock

import mockRequest from '@/mock/mockRequest.js'

import userMock from '@/mock/userMock.js'

function registMock(obj){

for(let key in userMock){
    mockRequest.registUrl(key,userMock[key])
}

}

registMock(userMock);

export default mockRequest
main.js 中指定mockRequest

import mockRequest from './mock/mockRequest.js'
// 加载mock
import mock from './mock/index.js'

// mock拦截 拦截失败走request
mockRequest.setRequest(request);
Vue.prototype.$request = mockRequest;

import Vue from 'vue'
import store from './store'
import App from './App'
import request from './common/request/request.js'
import mockRequest from './mock/mockRequest.js'
// 加载mock
import mock from './mock/index.js'

import Json from './Json' //测试用数据
/**

  • 因工具函数属于公司资产, 所以直接在Vue实例挂载几个常用的函数
  • 所有测试用数据均存放于根目录json.js
  • css部分使用了App.vue下的全局样式和iconfont图标,有需要图标库的可以留言。
  • 示例使用了uni.scss下的变量, 除变量外已尽量移除特有语法,可直接替换为其他预处理器使用

*/
const msg = (title, duration=1500, mask=false, icon='none')=>{

//统一提示方便全局修改
if(Boolean(title) === false){
    return;
}
uni.showToast({
    title,
    duration,
    mask,
    icon
});

}
const json = type=>{

//模拟异步请求数据
return new Promise(resolve=>{
    setTimeout(()=>{
        resolve(Json[type]);
    }, 500)
})

}

const prePage = ()=>{

let pages = getCurrentPages();
let prePage = pages[pages.length - 2];
// #ifdef H5
return prePage;
// #endif
return prePage.$vm;

}

// 全局配置
request.setConfig({
baseUrl: 'https://www.cookegc.com', // 此为测试地址,需加入到域名白名单,或者更改为您自己的线上地址即可
dataType: 'json', // 可删除,默认为json
responseType: 'text', // 可删除,默认为text
// 设置请求头,支持所有请求头设置,也可不设置,去掉header就行
header: {

'token': 'token from global',
'content-type': 'application/json' 

}
})

// 设置请求拦截器
request.interceptors.request(config => {
// 配置参数和全局配置相同,此优先级最高,会覆盖在其他地方的相同配置参数

// 追加请求头,推荐
// config.header['content-type'] = 'application/json';
// config.header.token = 'token from interceptors';
let token = uni.getStorageSync('token');
// 覆盖请求头
config.header = {

// 'content-type': 'application/json',
'token': token

}

// return false; // 终止请求
// return Promise.reject('error from request interceptors'); // 向外层抛出错误,用catch捕获
return config; // 返回修改后的配置,如未修改也需添加这行
})

// 设置响应拦截器
request.interceptors.response(res => {
// 接收请求,执行响应操作
// 您的逻辑......

// return false; // 阻止返回,页面不会接收返回值
// return {message: '自定义值,来自拦截器'}; // 返回您自定义的值,将覆盖原始返回值
// return Promise.reject('error from response interceptors') // 向外层抛出错误,用catch捕获
return res; // 原样返回
})

// mock拦截 拦截失败走request
mockRequest.setRequest(request);
Vue.prototype.$request = mockRequest;

// 挂载到全局vue实例上,在页面中可以使用this.$request调用request实例下相应方法
// Vue.prototype.$request = request;

Vue.config.productionTip = false
Vue.prototype.$fire = new Vue();
Vue.prototype.$store = store;
Vue.prototype.$api = {msg, json, prePage};

App.mpType = 'app'

const app = new Vue({

...App

})
app.$mount()

使用demo

this.$request.get("/userInfo").then(res=>{

console.log('index.vue userInfo',res);

})

上一篇:学习vue3之路day2


下一篇:springcloud gateway nginx header 丢失