需求

实现params参数格式自定义序列化

  1. // params 序列化 - 1
  2. axios.get('/more/params', {
  3. params: new URLSearchParams('a=1&b=2')
  4. }).then(res => {
  5. console.log(res)
  6. }).catch(err => {
  7. console.error(err)
  8. })
  9. // params 序列化 - 2 默认规则(自己实现),特殊字符保持不变
  10. axios.get('/more/params', {
  11. params: { c: 3, d: [4, 4, 4, 4] }
  12. }).then(res => {
  13. console.log(res)
  14. }).catch(err => {
  15. console.error(err)
  16. })
  17. // params 序列化 - 3 特殊字符会encode
  18. axios.get('/more/params', {
  19. params: {
  20. e: [5, 5, 5, 5],
  21. f: 5
  22. },
  23. paramsSerializer(data) {
  24. return qs.stringify(data)
  25. }
  26. }).then(res => {
  27. console.log(res)
  28. }).catch(err => {
  29. console.error(err)
  30. })

代码实现

类型声明


export interface AxiosRequestConfig {
   // ...
  paramsSerializer?: (params: any) => string
}

修改buildUrl逻辑

export function buildURL(url: string, params?: any, paramsSerializer?: (params: any) => string): string {
  if (!params) {
    return url
  }
  let serializedParams = ''

  // 传入了 paramsSerializer 优先级最高
  if (paramsSerializer) {
    serializedParams = paramsSerializer(params)
  } else if (isURLSearchParams(params)) {
    serializedParams = params.toString()
  } else {
    const parts: string[] = []
    Object.keys(params).forEach(key => {
      const value = params[key]
      if (value === undefined || value === null) {
        return
      }
      // 统一处理为数组
      let values = []
      if (Array.isArray(value)) {
        key += '[]'
        values = value
      } else {
        values = [value]
      }

      // 拼接参数
      values.forEach(val => {
        if (isDate(val)) {
          val = (val as Date).toISOString()
        }
        if (isPlainObject(val)) {
          val = JSON.stringify(val as Object)
        }
        parts.push(`${encode(key)}=${encode(val)}`)
      })
    })

    serializedParams = parts.join('&')
  }


  if (serializedParams) {
    // 去掉锚点# (对于后端没有用)
    const markIndex = url.indexOf('#')
    if (markIndex !== -1) {
      url = url.slice(0, markIndex)
    }
    // 如果有? 继续拼接&,否则加上?
    url += url.indexOf('?') !== -1 ? `&${serializedParams}` : `?${serializedParams}`
  }
  return url
}

修改transformUrl

function transformUrl(config: AxiosRequestConfig) {
  const { url, params, paramsSerializer } = config
  return buildURL(url || '', params, paramsSerializer)
}