js实用方法封装

快速获取路由参数

地址示例:const url = 'https://www.baidu.com/?why=baidu&age=18'

首先将url通过?号分割,取下表[1]的值

url.split('?')[1]  
// why=baidu&age=18

第二步 将参数&替换成 "," 符号

url.split('?')[1].replace(/&/g, '","')  
 // why=baidu","age=18

第三步 将 = 号改为 : 号,此时已经基本能看到JSON格式

url.split('?')[1].replace(/&/g, '","').replace(/=/g, '":"')  
// why:baidu","age:18

最后,将最外层使用"包括住,并通过JSON.parse即可转化为对象类型
完整代码

const getParams = URL => JSON.parse(`{"${URL.split('?')[1].replace(/&/g, '","').replace(/=/g, '":"')}"}`)
console.log(getParams(url));
// {"why:baidu","age:18"}

计算两个日期之差

const dayDiff = (date1, date2) => Math.ceil(Math.abs(date1.getTime() - date2.getTime()) / 86400000);

dayDiff(new Date("2021-10-21"), new Date("2022-02-12"))

字符串替换

const render = (template, data) => {
  if (!data) return template;
  
  if (Array.isArray(data)) {
    for(let i = 0; i < data.length; i++) 
    template = template.replace(new RegExp('\\{' + i + '\\}', 'g'), data[i]);
  } else {
    for (let key in data) {
      template = template.replace(new RegExp('\\{' + key + '\\}', 'g'), data[key]);
    }
  }

  return template;
}

const temp = '我的名字是{name}, 我的年龄是{age}';
const temp1 = '我的名字是{0}, 我的年龄是{1}';
const newTemp = render(temp, {name: 'gzc'});
const newTemp1 = render(temp1, ['gzc']);
console.log(newTemp)
console.log(newTemp1)

下载文件

    const res = await request(...);
    const blob = new Blob([res]);
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    document.body.appendChild(a); //兼容火狐,将a标签添加到body当中
    a.href = url;
    a.download = decodeURI('模板.xlsx');
    a.target = '_blank'; // a标签增加target属性
    a.click();
    a.remove(); //移除a标签
    window.URL.revokeObjectURL(url);

umi http请求封装

/*
 * @Author: 郭智成
 * @Date: 2022-07-22 11:35:10
 * @FilePath: /car_mgr_web/src/request/index.ts
 * @Description: 网络请求
 */
import { extend } from 'umi-request';
import { codeMessage, download, errorHandler, resolveBlob } from './config';
import { getToken } from '@/utils/storage';
import { notification } from 'antd';
import { history } from 'umi';

type RequestApi = {
  url: string,
  method: 'GET' | 'POST' | 'PUT' | 'DELETE',
  options?: Record<string, any>,
}

interface RequestParams {
  /** 需要放在body内传递的参数 */
  data?: Record<string, any>,

  /** 拼接在url地址后的参数 */
  params?: Record<string, any>,

  /** 扩展字段 */
  option?: Record<string, any>,
}

interface FormData {
  /** 要上传文件资源的路径。 */
  filePath: string
  /** 文件对应的参数名 */
  fileKey: string
  [key: string]: any
}

const { NODE_ENV } = process.env;
const BASE_URL = NODE_ENV === 'development' ? '' : location.origin;

const timeout = 10000;
const apiBasePath = '/api/plat';
// zip配置
const mimeMap = {
  xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  zip: 'application/zip',
};

function createClient () {
  /** 配置request请求时的默认参数 */
  return extend({
    errorHandler, // 默认错误处理
    // credentials: 'include', // 默认请求是否带上cookie
    prefix: apiBasePath,
  });
}
export const request = createClient();

/** 请求拦截 */
request.interceptors.request.use((url: string, options: any) => {
  const token = getToken();
  options.headers = {
    ...options.headers,
    Authorization: `Bearer ${token}`,
  };
  return { url: BASE_URL + url, options };
});

/** 响应拦截 */
request.interceptors.response.use(async (response: Response) => {
  let notificationOpt: null | { message: string, description: string } = null;
  const { status, url } = response || {};

  if (status == 200) {
    let data = await response.clone().json();
    const { respCode, respMsg, success } = data;
    if (success) return response;

    const errorText = respMsg || codeMessage[respCode];
    if (respCode === '401') {
      history.replace('/login')
    }

    console.error(`${errorText} code: ${respCode}: ${url}`);
    notificationOpt = {
      message: `${errorText} code: ${respCode}: ${url}`,
      description: '请求错误',
    };
  }

  if (!response) {
    notificationOpt = {
      message: '网络开小差了,无法连接服务器',
      description: '请求错误',
    };
  }

  !!notificationOpt && notification.error(notificationOpt);
});

/** 统一请求接口 */
const requestApi = ({
  url,
  method,
  options = {}
}: RequestApi) => {
  return request<any>(url, {
    method,
    timeout,
    ...options,
  });
}

/**
 * get请求
 * @param param1 params 请求参数
 * @param param1 option 其余扩展参数
 * @returns 
 */
const GET = (url: string, requestParams?: RequestParams) => {
  const { params, option = {} } = requestParams || {};
  const options = { params, ...option };
  return requestApi({ url, method: 'GET', options });
}

/**
 * post请求
 * @param requestParams data 放入body的参数
 * @param requestParams params 请求参数
 * @param requestParams option 其余扩展参数
 * @returns 
 */
const POST = <T>(url: string, data?: Record<string, any>, requestParams?: RequestParams): Promise<T> => {
  const {
    params,
    option = {
      headers: {
        'Content-Type': 'application/json',
      },
    }
  } = requestParams || {};
  const options = { data, params, ...option };
  return requestApi({ url, method: 'POST', options });
}
/**
 * delete请求
 * @param param1 params 请求参数
 * @param param1 option 其余扩展参数
 * @returns 
 */
const DELETE = (url: string, config?: RequestParams) => {
  const {
    option = {
      headers: {
        'Content-Type': 'application/json',
      },
    }
  } = config || {};
  const options = { ...option };
  return requestApi({ url, method: 'DELETE', options });
}
/**
 * put请求
 * @param data body参数
 * @param params 请求参数
 * @param option 其余扩展参数
 * @returns 
 */
const PUT = (url: string, requestParams: RequestParams) => {
  const { data, params, option = {} } = requestParams;
  const options = { data, params, ...option };
  return requestApi({ url, method: 'PUT', options });
}
/**
 * 上传请求
 * @param data 需要上传的文件信息
 * @returns 
 */
const upload = (url: string, data: FormData) => {
  const options = {
    data,
    headers: {
      'Content-Type': 'multipart/form-data',
    },
  };
  return requestApi({ url, method: 'POST', options });
}

/** 下载zip */
const downLoadZip = (url: string) => {
  requestApi({
    url, 
    method: 'GET',
    options: {
      responseType: 'blob',
      getResponse: true,
    }
  }).then((res) => {
    resolveBlob(res, mimeMap.zip);
  });
}

/** 下载文件 */
const downLoadFile = async(url: string, params: any, fileName: string) => {
  return requestApi({
    url, 
    method: 'POST',
    options: {params, responseType: 'blob'}
  }).then((data) => {
    download(data, fileName);
  });
}

const pages = <T = any>(url: string, { current = 1, pageSize = 10, ...others } = {}): Promise<PageResult<T>> => {
  return POST(url, { currentPage: current, pageSize, ...others })
    .then((res: any) => {
      const { total, size, current, pages, records } = res?.data as any;
      return {
        success: true,
        total,
        pages,
        size,
        current,
        data: records,
      }
    })
}

export {
  GET,
  POST,
  DELETE,
  PUT,
  upload,
  downLoadFile,
  downLoadZip,
  pages,
};
  
type PageResult<T> = {
  success: boolean,
  /** 总记录数 */
  total: number,
  /** 总页数 */
  pages: number,
  /** 每页条数 */
  size: number
  /** 当前页数 */
  current: number
  /** 记录数组 */
  data: T[]
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • 方法 在一个对象中绑定函数,称为这个对象的方法。 在JavaScript中,对象的定义是这样的: 但是,如果我们给...
    wit92阅读 453评论 0 0
  • 推荐阅读:前端常见跨域解决方案 写的很全面很详细 https://segmentfault.com/a/11900...
    Jc_wo阅读 1,252评论 0 0
  • 1. javascript的typeof返回哪些数据类型. 答案:string,boolean,number,un...
    梦里梦不到的梦_b5c8阅读 686评论 0 0
  • 1. javascript的typeof返回哪些数据类型. 答案:string,boolean,number,un...
    O蚂蚁O阅读 8,456评论 5 248
  • 1. javascript的typeof返回哪些数据类型. 答案:string,boolean,number,un...
    townof1997阅读 247评论 0 0