Skip to content

Commit

Permalink
feat(utils): 新增 createUrlQueryString, parseUrlQueryString
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Aug 25, 2020
1 parent f78649a commit 7cd3152
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/utils/__snapshots__/createUrlQueryString.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`createUrlQueryString 表现正常 1`] = `"0=0%20%3D%20%26%20%3F%F0%9F%98%81&2=xxx&x=1%2F%2F%24%256&%F0%9F%98%81%F0%9F%A5%B3=hello"`;
14 changes: 14 additions & 0 deletions src/utils/createUrlQueryString.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createUrlQueryString } from './createUrlQueryString'

describe('createUrlQueryString', () => {
test('表现正常', () => {
const parameters = {
'x': '1//$%6',
'2': 'xxx',
'0': '0 = & ?😁',
'😁🥳': 'hello',
}
const query = createUrlQueryString(parameters)
expect(query).toMatchSnapshot()
})
})
21 changes: 21 additions & 0 deletions src/utils/createUrlQueryString.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { AnyObject } from '../types'

/**
* 创建 url 查询字符串。
*
* @param parameters 查询参数
* @returns 返回 url 查询字符串
* @example
* ```typescript
* createUrlQueryString({ x: 1, y: 'z' }) // => x=1&y=z
* ```
*/
export function createUrlQueryString(parameters: AnyObject) {
const parts: string[] = []
for (const key of Object.keys(parameters)) {
parts.push(
`${encodeURIComponent(key)}=${encodeURIComponent(parameters[key])}`,
)
}
return parts.join('&')
}
2 changes: 2 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from 'lodash-es'
export * from './base64'
export * from './bindEvent'
export * from './createSubmit'
export * from './createUrlQueryString'
export * from './dedent'
export * from './EventBus'
export * from './formatNumber'
Expand All @@ -37,6 +38,7 @@ export * from './md5'
export * from './move'
export * from './omitStrict'
export * from './onceMeanwhile'
export * from './parseUrlQueryString'
export * from './pickStrict'
export * from './placeKitten'
export * from './readFile'
Expand Down
30 changes: 30 additions & 0 deletions src/utils/parseUrlQueryString.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { createUrlQueryString } from './createUrlQueryString'
import { Merge } from '../types'
import { parseUrlQueryString } from './parseUrlQueryString'

describe('parseUrlQueryString', () => {
test('表现正常', () => {
const parameters = {
'x': '1//$%6',
'2': 'xxx',
'0': '0 = & ?😁',
'😁🥳': 'hello',
'age': '20',
}
expect(parseUrlQueryString(createUrlQueryString(parameters))).toEqual(
parameters,
)
expect(parseUrlQueryString(`?${createUrlQueryString(parameters)}`)).toEqual(
parameters,
)
expect(
parseUrlQueryString<Merge<typeof parameters, { age: number }>>(
createUrlQueryString(parameters),
q => ({ ...q, age: +q.age }),
),
).toEqual({
...parameters,
age: +parameters.age,
})
})
})
38 changes: 38 additions & 0 deletions src/utils/parseUrlQueryString.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export interface ParseUrlQueryStringFormat<T extends Record<string, any>> {
(parameters: Record<keyof T, string>): T
}

/**
* 解析 url 查询字符串。
*
* 兼容以 `?` 开头的查询字符串,因此你可以直接传入 `location.search` 的值。
*
* @param query 查询字符串
* @param format 格式化查询参数
* @returns 返回 url 查询参数
* @example
* ```typescript
* parseUrlQueryString('x=1&y=z') // => { x: '1', y: 'z' }
* parseUrlQueryString('?x=1&y=z') // => { x: '1', y: 'z' }
* parseUrlQueryString(
* 'x=1&y=z',
* parameters => ({
* ...parameters,
* x: Number(parameters.x),
* }),
* ) // => { x: 1, y: 'z' }
* ```
*/
export function parseUrlQueryString<
T extends Record<string, any> = Record<string, any>
>(query: string, format?: ParseUrlQueryStringFormat<T>): T {
const parameters: T = {} as any
query = query.charAt(0) === '?' ? query.substring(1) : query
for (const pair of query.split('&')) {
const [key, value] = pair.split('=')
const decodedKey = decodeURIComponent(key)
const decodedValue = decodeURIComponent(value)
;(parameters as any)[decodedKey] = decodedValue
}
return typeof format === 'function' ? format(parameters) : parameters
}

0 comments on commit 7cd3152

Please sign in to comment.