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

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

uni.request promise插件  https://ext.dcloud.net.cn/plugin?id=289

建目录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);
})

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐