update
parent
554fc20cfa
commit
5c203ad5f5
|
@ -0,0 +1,10 @@
|
|||
## ajax的全新封装
|
||||
> 统一走fetch的风格。
|
||||
|
||||
|
||||
### 版本
|
||||
> 共有2个版本, 一个传统版本, 基于`XMLHttpRequest`; 另一个是新一代版本, 基于`window.fetch()`。2个版本功能基本一致, 使用上没有区别。
|
||||
|
||||
`**注意:**`
|
||||
|
||||
由于`window.fetch()`只支持`http/https`协议, 所以在一些特殊的环境下(如electron等), 请使用传统版。
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "@bytedo/fetch",
|
||||
"version": "1.0.0",
|
||||
"description": "全新的ajax封装。分2个版本, 一个基于XMLHttpRequest, 一个基于window.fetch",
|
||||
"main": "dist/index.js",
|
||||
"directories": {
|
||||
"lib": "dist/lib"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/bytedo/fetch.git"
|
||||
},
|
||||
"keywords": ["fetch", "axois", "request", "ajax"],
|
||||
"author": "yutent",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/bytedo/fetch/issues"
|
||||
},
|
||||
"homepage": "https://github.com/bytedo/fetch#readme"
|
||||
}
|
|
@ -0,0 +1,445 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent.io@gmail.com)
|
||||
* @date 2018-03-25 23:59:13
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
import Format from './lib/format'
|
||||
|
||||
// 本地协议/头 判断正则
|
||||
const rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/
|
||||
const log = console.log
|
||||
|
||||
const noop = function(e, res) {
|
||||
this.defer.resolve(res)
|
||||
}
|
||||
|
||||
let isLocal = false
|
||||
try {
|
||||
isLocal = rlocalProtocol.test(location.protocol)
|
||||
} catch (e) {}
|
||||
|
||||
let originAnchor = document.createElement('a')
|
||||
originAnchor.href = location.href
|
||||
|
||||
const NOBODY_METHODS = ['GET', 'HEAD']
|
||||
const ERRORS = {
|
||||
10001: 'Argument url is required',
|
||||
10012: 'Parse error',
|
||||
10100: 'Request canceled',
|
||||
10104: 'Request pending...',
|
||||
10200: 'Ok',
|
||||
10204: 'No content',
|
||||
10304: 'Not modified',
|
||||
10500: 'Internal Server Error',
|
||||
10504: 'Connected timeout'
|
||||
}
|
||||
|
||||
const FORM_TYPES = {
|
||||
form: 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
json: 'application/json; charset=UTF-8',
|
||||
text: 'text/plain; charset=UTF-8'
|
||||
}
|
||||
|
||||
const convert = {
|
||||
text(val) {
|
||||
return val
|
||||
},
|
||||
xml(val, xml) {
|
||||
return xml !== undefined ? xml : Format.parseXML(val)
|
||||
},
|
||||
html(val) {
|
||||
return Format.parseHTML(val)
|
||||
},
|
||||
json(val) {
|
||||
return JSON.parse(val)
|
||||
},
|
||||
script(val) {
|
||||
return Format.parseJS(val)
|
||||
}
|
||||
}
|
||||
|
||||
class _Request {
|
||||
constructor(url = '', method = 'GET', param = {}) {
|
||||
if (!url) {
|
||||
throw new Error(ERRORS[10001])
|
||||
}
|
||||
|
||||
// url规范化
|
||||
url = url.replace(/#.*$/, '')
|
||||
|
||||
if (request.BASE_URL) {
|
||||
if (!/^([a-z]+:|\/\/)/.test(url)) {
|
||||
url = request.BASE_URL + url
|
||||
}
|
||||
}
|
||||
|
||||
method = method.toUpperCase()
|
||||
|
||||
this.xhr = new XMLHttpRequest()
|
||||
this.defer = Promise.defer()
|
||||
this.opt = {
|
||||
url,
|
||||
method,
|
||||
headers: {},
|
||||
data: {},
|
||||
dataType: 'text',
|
||||
withCredentials: false // 跨域选项,是否验证凭证
|
||||
}
|
||||
|
||||
// 取消网络请求
|
||||
this.defer.promise.abort = () => {
|
||||
this.cancel = true
|
||||
this.xhr.abort()
|
||||
}
|
||||
this.__next__(Object.assign({}, request.__INIT__, param))
|
||||
return this.defer.promise
|
||||
}
|
||||
|
||||
__next__(param) {
|
||||
/* -------------------------------------------------------------- */
|
||||
/* ------------------------ 1»» 配置头信息 ---------------------- */
|
||||
/* -------------------------------------------------------------- */
|
||||
if (param.headers) {
|
||||
Object.assign(this.opt.headers, param.headers)
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* --------- 2»» 设置表单类型, 其中 form-data不能手动设置 ---------- */
|
||||
/* -------------------------------------------------------------- */
|
||||
let hasAttach = false
|
||||
if (param.formType) {
|
||||
switch (param.formType) {
|
||||
case 'form':
|
||||
this.__set__('form')
|
||||
break
|
||||
case 'json':
|
||||
this.__set__('json')
|
||||
break
|
||||
case 'form-data':
|
||||
this.opt.method = 'POST'
|
||||
hasAttach = true
|
||||
break
|
||||
default:
|
||||
if (NOBODY_METHODS.includes(this.opt.method)) {
|
||||
this.__set__('form')
|
||||
} else {
|
||||
this.__set__('text')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.__set__('form')
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* ------------------- 3»» 设置缓存 ---------------------------- */
|
||||
/* -------------------------------------------------------------- */
|
||||
if (param.cache) {
|
||||
if (NOBODY_METHODS.includes(this.opt.method)) {
|
||||
this.opt.cache = true
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* ------------------- 4»» 设置超时时间(毫秒) --------------------- */
|
||||
/* -------------------------------------------------------------- */
|
||||
param.timeout = param.timeout >>> 0
|
||||
if (param.timeout > 0) {
|
||||
this.opt.timeout = param.timeout
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* -------------------------- 5»» 请求的内容 --------------------- */
|
||||
/* -------------------------------------------------------------- */
|
||||
if (param.data) {
|
||||
let type = typeof param.data
|
||||
|
||||
switch (type) {
|
||||
case 'number':
|
||||
case 'string':
|
||||
this.__set__('text')
|
||||
this.opt.data = param.data
|
||||
break
|
||||
case 'object':
|
||||
// 解析表单DOM
|
||||
if (param.data.nodeName === 'FORM') {
|
||||
this.opt.method = param.data.method.toUpperCase() || 'POST'
|
||||
|
||||
this.opt.data = Format.parseForm(param.data)
|
||||
hasAttach = this.opt.data.constructor === FormData
|
||||
|
||||
if (hasAttach) {
|
||||
delete this.opt.headers['content-type']
|
||||
}
|
||||
// 如果是一个 FormData对象
|
||||
// 则直接改为POST
|
||||
} else if (param.data.constructor === FormData) {
|
||||
hasAttach = true
|
||||
this.opt.method = 'POST'
|
||||
delete this.opt.headers['content-type']
|
||||
this.opt.data = param.data
|
||||
} else {
|
||||
// 有附件,则改为FormData
|
||||
if (hasAttach) {
|
||||
this.opt.data = Format.mkFormData(param.data)
|
||||
} else {
|
||||
this.opt.data = param.data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* -------------------------- 6»» 处理跨域 --------------------- */
|
||||
/* -------------------------------------------------------------- */
|
||||
if (param.withCredentials) {
|
||||
this.opt.withCredentials = true
|
||||
}
|
||||
try {
|
||||
let anchor = document.createElement('a')
|
||||
anchor.href = this.opt.url
|
||||
|
||||
this.opt.crossDomain =
|
||||
originAnchor.protocol !== anchor.protocol ||
|
||||
originAnchor.host !== anchor.host
|
||||
} catch (err) {}
|
||||
|
||||
// 6.1»» 进一步处理跨域
|
||||
// 非跨域或跨域但支持Cors时自动加上一条header信息,用以标识这是ajax请求
|
||||
// 如果是跨域,开启Cors会需要服务端额外返回一些headers
|
||||
|
||||
if (this.opt.crossDomain) {
|
||||
if (this.opt.withCredentials) {
|
||||
this.xhr.withCredentials = true
|
||||
this.opt.headers['X-Requested-With'] = 'XMLHttpRequest'
|
||||
}
|
||||
} else {
|
||||
this.opt.headers['X-Requested-With'] = 'XMLHttpRequest'
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* ------------- 7»» 根据method类型, 处理g表单数据 ---------------- */
|
||||
/* -------------------------------------------------------------- */
|
||||
// 是否允许发送body
|
||||
let allowBody = !NOBODY_METHODS.includes(this.opt.method)
|
||||
if (allowBody) {
|
||||
if (!hasAttach) {
|
||||
if (param.formType === 'json') {
|
||||
this.opt.data = JSON.stringify(this.opt.data)
|
||||
} else {
|
||||
this.opt.data = Format.param(this.opt.data)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 否则拼接到url上
|
||||
this.opt.data = Format.param(this.opt.data)
|
||||
|
||||
if (this.opt.data) {
|
||||
this.opt.url += (/\?/.test(this.opt.url) ? '&' : '?') + this.opt.data
|
||||
}
|
||||
|
||||
if (this.opt.cache === false) {
|
||||
this.opt.url +=
|
||||
(/\?/.test(this.opt.url) ? '&' : '?') + '_=' + Math.random()
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* ------------- 8»» 设置响应的数据类型 ---------------- */
|
||||
/* -------------------------------------------------------------- */
|
||||
// arraybuffer | blob | document | json | text
|
||||
if (param.dataType) {
|
||||
this.opt.dataType = param.dataType.toLowerCase()
|
||||
}
|
||||
this.xhr.responseType = this.opt.dataType
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* ------------- 9»» 构造请求 ---------------- */
|
||||
/* -------------------------------------------------------------- */
|
||||
|
||||
// response ready
|
||||
this.xhr.onreadystatechange = ev => {
|
||||
if (this.opt.timeout > 0) {
|
||||
this.opt['time' + this.xhr.readyState] = ev.timeStamp
|
||||
if (this.xhr.readyState === 4) {
|
||||
this.opt.isTimeout =
|
||||
this.opt.time4 - this.opt.time1 > this.opt.timeout
|
||||
}
|
||||
}
|
||||
|
||||
if (this.xhr.readyState !== 4) {
|
||||
return
|
||||
}
|
||||
|
||||
this.__dispatch__(this.opt.isTimeout)
|
||||
}
|
||||
|
||||
// 9.1»» 初始化xhr
|
||||
this.xhr.open(this.opt.method, this.opt.url, true)
|
||||
|
||||
// 9.2»» 设置头信息
|
||||
for (let i in this.opt.headers) {
|
||||
this.xhr.setRequestHeader(i, this.opt.headers[i])
|
||||
}
|
||||
|
||||
// 9.3»» 发起网络请求
|
||||
this.xhr.send(this.opt.data)
|
||||
|
||||
// 9.4»» 超时处理
|
||||
if (this.opt.timeout && this.opt.timeout > 0) {
|
||||
this.xhr.timeout = this.opt.timeout
|
||||
}
|
||||
}
|
||||
|
||||
__set__(type) {
|
||||
this.opt.headers['content-type'] = FORM_TYPES[type]
|
||||
}
|
||||
|
||||
__dispatch__(isTimeout) {
|
||||
let result = {
|
||||
status: 200,
|
||||
statusText: 'ok',
|
||||
text: '',
|
||||
body: '',
|
||||
error: null
|
||||
}
|
||||
|
||||
// 主动取消
|
||||
if (this.cancel) {
|
||||
return this.__cancel__(result)
|
||||
}
|
||||
|
||||
// 超时
|
||||
if (isTimeout) {
|
||||
return this.__timeout__(result)
|
||||
}
|
||||
|
||||
// 是否请求成功(resful规范)
|
||||
let isSucc = this.xhr.status >= 200 && this.xhr.status < 400
|
||||
|
||||
let headers = this.xhr.getAllResponseHeaders().split('\n') || []
|
||||
let contentType = ''
|
||||
|
||||
//处理返回的 Header, 拿到content-type
|
||||
for (let it of headers) {
|
||||
it = it.trim()
|
||||
if (it) {
|
||||
it = it.split(':')
|
||||
let tmp = it.shift().toLowerCase()
|
||||
if (tmp === 'content-type') {
|
||||
contentType = it
|
||||
.join(':')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isSucc) {
|
||||
result.status = this.xhr.status
|
||||
if (result.status === 204) {
|
||||
result.statusText = ERRORS[10204]
|
||||
} else if (result.status === 304) {
|
||||
result.statusText = ERRORS[10304]
|
||||
}
|
||||
} else {
|
||||
result.status = this.xhr.status || 500
|
||||
result.statusText = this.xhr.statusText || ERRORS[10500]
|
||||
result.error = new Error(result.statusText)
|
||||
}
|
||||
// log(this.opt.dataType, this.xhr)
|
||||
switch (this.opt.dataType) {
|
||||
case 'arraybuffer':
|
||||
case 'blob':
|
||||
case 'document':
|
||||
case 'json':
|
||||
result.text = result.body = this.xhr.response
|
||||
break
|
||||
// text
|
||||
default:
|
||||
try {
|
||||
//处理返回的数据
|
||||
let dataType = contentType.match(/json|xml|script|html/)
|
||||
|
||||
dataType = (dataType && dataType[0].toLowerCase()) || 'text'
|
||||
|
||||
result.text = this.xhr.response
|
||||
result.body = convert[dataType](result.text, this.xhr.response)
|
||||
} catch (err) {
|
||||
result.error = err
|
||||
result.statusText = ERRORS[10012]
|
||||
}
|
||||
break
|
||||
}
|
||||
this.__success__(isSucc, result)
|
||||
}
|
||||
|
||||
__success__(isSucc, result) {
|
||||
if (isSucc) {
|
||||
this.defer.resolve(result)
|
||||
} else {
|
||||
this.defer.reject(result)
|
||||
}
|
||||
delete this.xhr
|
||||
delete this.opt
|
||||
delete this.defer
|
||||
}
|
||||
|
||||
__cancel__(result) {
|
||||
result.status = 0
|
||||
result.statusText = ERRORS[10100]
|
||||
result.error = new Error(ERRORS[10100])
|
||||
|
||||
this.defer.reject(result)
|
||||
|
||||
delete this.xhr
|
||||
delete this.opt
|
||||
delete this.defer
|
||||
}
|
||||
|
||||
__timeout__(result) {
|
||||
result.status = 504
|
||||
result.statusText = ERRORS[10504]
|
||||
result.error = new Error(ERRORS[10504])
|
||||
|
||||
this.defer.reject(result)
|
||||
|
||||
delete this.xhr
|
||||
delete this.opt
|
||||
delete this.defer
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.request) {
|
||||
window.request = {
|
||||
get(url, param = {}) {
|
||||
return new _Request(url, 'GET', param)
|
||||
},
|
||||
post(url, param = {}) {
|
||||
return new _Request(url, 'POST', param)
|
||||
},
|
||||
upload(url, param = {}) {
|
||||
param.formType = 'form-data'
|
||||
return this.post(url, param)
|
||||
},
|
||||
download(url, param = {}) {
|
||||
param.dataType = 'blob'
|
||||
return this.get(url, param)
|
||||
},
|
||||
open(url, method = 'GET', param = {}) {
|
||||
if (typeof method === 'object') {
|
||||
param = method
|
||||
method = 'GET'
|
||||
}
|
||||
return new _Request(url, method, param)
|
||||
},
|
||||
version: '2.0.0-normal',
|
||||
init(param = {}) {
|
||||
this.__INIT__ = param
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default request
|
|
@ -0,0 +1,224 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent.io@gmail.com)
|
||||
* @date 2016-11-26 16:35:45
|
||||
*
|
||||
*/
|
||||
|
||||
const toS = Object.prototype.toString
|
||||
const doc = window.document
|
||||
const encode = encodeURIComponent
|
||||
const decode = decodeURIComponent
|
||||
const svgTags =
|
||||
'circle,defs,ellipse,image,line,path,polygon,polyline,rect,symbol,text,use'
|
||||
|
||||
const TagHooks = function() {
|
||||
this.option = doc.createElement('select')
|
||||
this.thead = doc.createElement('table')
|
||||
this.td = doc.createElement('tr')
|
||||
this.area = doc.createElement('map')
|
||||
this.tr = doc.createElement('tbody')
|
||||
this.col = doc.createElement('colgroup')
|
||||
this.legend = doc.createElement('fieldset')
|
||||
this._default = doc.createElement('div')
|
||||
this.g = doc.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
||||
|
||||
this.optgroup = this.option
|
||||
this.tbody = this.tfoot = this.colgroup = this.caption = this.thead
|
||||
this.th = this.td
|
||||
|
||||
// 处理svg
|
||||
svgTags.split(',').forEach(m => {
|
||||
this[m] = this.g
|
||||
})
|
||||
}
|
||||
|
||||
const Helper = {
|
||||
tagHooks: new TagHooks(),
|
||||
rtagName: /<([\w:]+)/,
|
||||
rxhtml: /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
|
||||
scriptTypes: {
|
||||
'text/javascript': 1,
|
||||
'text/ecmascript': 1,
|
||||
'application/ecmascript': 1,
|
||||
'application/javascript': 1
|
||||
},
|
||||
rhtml: /<|&#?\w+;/
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单序列化
|
||||
*/
|
||||
function serialize(p, obj, query) {
|
||||
var k
|
||||
if (Array.isArray(obj)) {
|
||||
obj.forEach(function(it, i) {
|
||||
k = p ? `${p}[${Array.isArray(it) ? i : ''}]` : i
|
||||
if (typeof it === 'object') {
|
||||
serialize(k, it, query)
|
||||
} else {
|
||||
query(k, it)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
for (let i in obj) {
|
||||
k = p ? `${p}[${i}]` : i
|
||||
if (typeof obj[i] === 'object') {
|
||||
serialize(k, obj[i], query)
|
||||
} else {
|
||||
query(k, obj[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
parseJS(code) {
|
||||
code = (code + '').trim()
|
||||
if (code) {
|
||||
if (code.indexOf('use strict') === 1) {
|
||||
let script = doc.createElement('script')
|
||||
script.text = code
|
||||
doc.head.appendChild(script).parentNode.removeChild(script)
|
||||
} else {
|
||||
eval(code)
|
||||
}
|
||||
}
|
||||
},
|
||||
parseXML(data, xml, tmp) {
|
||||
try {
|
||||
tmp = new DOMParser()
|
||||
xml = tmp.parseFromString(data, 'text/xml')
|
||||
} catch (e) {
|
||||
xml = void 0
|
||||
}
|
||||
|
||||
if (
|
||||
!xml ||
|
||||
!xml.documentElement ||
|
||||
xml.getElementsByTagName('parsererror').length
|
||||
) {
|
||||
console.error('Invalid XML: ' + data)
|
||||
}
|
||||
return xml
|
||||
},
|
||||
parseHTML(html) {
|
||||
let fragment = doc.createDocumentFragment().cloneNode(false)
|
||||
|
||||
if (typeof html !== 'string') {
|
||||
return fragment
|
||||
}
|
||||
|
||||
if (!Helper.rhtml.test(html)) {
|
||||
fragment.appendChild(document.createTextNode(html))
|
||||
return fragment
|
||||
}
|
||||
|
||||
html = html.replace(Helper.rxhtml, '<$1></$2>').trim()
|
||||
let tag = (Helper.rtagName.exec(html) || ['', ''])[1].toLowerCase()
|
||||
let wrap = Helper.tagHooks[tag] || Helper.tagHooks._default
|
||||
let firstChild = null
|
||||
|
||||
//使用innerHTML生成的script节点不会触发请求与执行text属性
|
||||
wrap.innerHTML = html
|
||||
let script = wrap.getElementsByTagName('script')
|
||||
if (script.length) {
|
||||
for (let i = 0, el; (el = script[i++]); ) {
|
||||
if (Helper.scriptTypes[el.type]) {
|
||||
let tmp = doc.createElement('script').cloneNode(false)
|
||||
el.attributes.forEach(function(attr) {
|
||||
tmp.setAttribute(attr.name, attr.value)
|
||||
})
|
||||
tmp.text = el.text
|
||||
el.parentNode.replaceChild(tmp, el)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((firstChild = wrap.firstChild)) {
|
||||
fragment.appendChild(firstChild)
|
||||
}
|
||||
|
||||
return fragment
|
||||
},
|
||||
parseForm(form) {
|
||||
let data = {}
|
||||
let hasAttach = false
|
||||
for (let i = 0, field; (field = form.elements[i++]); ) {
|
||||
switch (field.type) {
|
||||
case 'select-one':
|
||||
case 'select-multiple':
|
||||
if (field.name.length && !field.disabled) {
|
||||
for (let j = 0, opt; (opt = field.options[j++]); ) {
|
||||
if (opt.selected) {
|
||||
data[field.name] = opt.value || opt.text
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'file':
|
||||
if (field.name.length && !field.disabled) {
|
||||
data[field.name] = field.files[0]
|
||||
hasAttach = true
|
||||
}
|
||||
break
|
||||
case undefined:
|
||||
case 'submit':
|
||||
case 'reset':
|
||||
case 'button':
|
||||
break //按钮啥的, 直接忽略
|
||||
case 'radio':
|
||||
case 'checkbox':
|
||||
// 只处理选中的
|
||||
if (!field.checked) break
|
||||
default:
|
||||
if (field.name.length && !field.disabled) {
|
||||
data[field.name] = field.value
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果有附件, 改为FormData
|
||||
if (hasAttach) {
|
||||
return this.mkFormData(data)
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
},
|
||||
mkFormData(data) {
|
||||
let form = new FormData()
|
||||
for (let i in data) {
|
||||
let el = data[i]
|
||||
if (Array.isArray(el)) {
|
||||
el.forEach(function(it) {
|
||||
form.append(i + '[]', it)
|
||||
})
|
||||
} else {
|
||||
form.append(i, data[i])
|
||||
}
|
||||
}
|
||||
return form
|
||||
},
|
||||
param(obj) {
|
||||
if (!obj || typeof obj === 'string' || typeof obj === 'number') {
|
||||
return obj
|
||||
}
|
||||
|
||||
let arr = []
|
||||
let query = function(k, v) {
|
||||
if (/native code/.test(v)) {
|
||||
return
|
||||
}
|
||||
|
||||
v = typeof v === 'function' ? v() : v
|
||||
v = toS.call(v) === '[object File]' ? v : encode(v)
|
||||
|
||||
arr.push(encode(k) + '=' + v)
|
||||
}
|
||||
|
||||
if (typeof obj === 'object') {
|
||||
serialize('', obj, query)
|
||||
}
|
||||
|
||||
return arr.join('&')
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* 新一代版本
|
||||
* @author yutent<yutent.io@gmail.com>
|
||||
* @date 2020/07/31 18:59:47
|
||||
*/
|
||||
|
||||
import Format from './lib/format'
|
Loading…
Reference in New Issue