From 4483c8f3d3e1bd7bc7afa0e146d6e4706057d846 Mon Sep 17 00:00:00 2001 From: 4Ark Date: Mon, 11 May 2020 16:18:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9F=A5=E8=AF=A2=E5=80=BC=E4=B8=BA?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E6=97=B6=E7=9A=84=E5=88=86=E9=9A=94=E7=AC=A6?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20(#301)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 查询值为数组时的分隔符问题 * fix: 查询值为数组时的分隔符问题 * Update src/utils/query.js Co-authored-by: Donald Shen * fix: 去除 URLStringify Co-authored-by: Donald Shen --- src/el-data-table.vue | 4 +++- src/utils/query.js | 29 +++++++++++++++++++++-------- test/query.test.js | 29 +++++++++++++++++++++-------- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/el-data-table.vue b/src/el-data-table.vue index ddceed59..20e1c7b2 100644 --- a/src/el-data-table.vue +++ b/src/el-data-table.vue @@ -952,7 +952,9 @@ export default { const queryStr = (url.indexOf('?') > -1 ? '&' : '?') + - queryUtil.stringify(query, '=', '&') + Object.keys(query) + .map(k => `${k}=${decodeURIComponent(query[k])}`) + .join('&') // 请求开始 this.loading = loading diff --git a/src/utils/query.js b/src/utils/query.js index 8e270867..dc2c4dcb 100644 --- a/src/utils/query.js +++ b/src/utils/query.js @@ -1,25 +1,33 @@ export const valueSeparator = '~' export const paramSeparator = ',' +export const paramInnerSeparator = '|' export const queryFlag = 'q=' export const queryPattern = new RegExp(queryFlag + '.*' + paramSeparator) /** - * 转换query对象成可附在url上的字符串 - * qs.stringify只能自定义delimiter,不能自定义equal - * {a: 'a&b', b: true} => 'a~a%26b,b~true' - * + * 在浏览器地址栏的 URL 需要做额外处理:兼容持久化数组 + * 直接将数组 encode 时,数组[1,2]会先转成'1,2'再 encode 成 '1%2C2'。但 vue-router 会自动转义 url 参数,导致数组的 ',' 无法和键值对分隔符 ',' 区分开。解决方法:改变数组的分隔符 + * {a: 'a&b', b: true, d: [1,2,3]} => 'a~a%26b,b~true,d~%5B1%7C2%7C3%5D' * @param {object} query * @param {string} equal - 键和值的分隔符 * @param {string} delimiter - 键值对之间的分隔符 + * @param {string} arrayDelimiter - 数组项之间的分隔符 * @return {string} */ export function stringify( query, equal = valueSeparator, - delimiter = paramSeparator + delimiter = paramSeparator, + arrayDelimiter = paramInnerSeparator ) { return Object.keys(query) - .map(k => `${k}${equal}${encodeURIComponent(JSON.stringify(query[k]))}`) + .map(k => { + // 数组即便 encode 也会被自动转义,使用别的分割符 + const v = JSON.stringify(query[k]) + .split(',') + .join(arrayDelimiter) + return `${k}${equal}${encodeURIComponent(v)}` + }) .join(delimiter) } @@ -36,13 +44,18 @@ export function stringify( export function parse( query, equal = valueSeparator, - delimiter = paramSeparator + delimiter = paramSeparator, + arrayDelimiter = paramInnerSeparator ) { return query .split(delimiter) .map(param => param.split(equal)) .reduce((obj, [k, v]) => { - obj[k] = JSON.parse(decodeURIComponent(v)) + // 替换回逗号 + const value = decodeURIComponent(v) + .split(arrayDelimiter) + .join(',') + obj[k] = JSON.parse(value) return obj }, {}) } diff --git a/test/query.test.js b/test/query.test.js index 8105b4aa..3823dbcf 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1,6 +1,7 @@ import { valueSeparator, paramSeparator, + paramInnerSeparator, queryFlag, stringify, parse, @@ -10,13 +11,24 @@ import { } from '../src/utils/query' const query = { - obj: {a: '1', b: 'b&c'}, - str(equal = valueSeparator, delimiter = paramSeparator) { - return `a${equal}${encodeURIComponent( - JSON.stringify('1') - )}${delimiter}b${equal}${encodeURIComponent(JSON.stringify('b&c'))}` + obj: {a: '1', b: 'b&c', d: ['1', '2', '3']}, + str( + equal = valueSeparator, + delimiter = paramSeparator, + arrayDelimiter = paramInnerSeparator + ) { + return [ + `a${equal}${encodeURIComponent(JSON.stringify('1'))}`, + `b${equal}${encodeURIComponent(JSON.stringify('b&c'))}`, + `d${equal}${encodeURIComponent( + JSON.stringify(['1', '2', '3']) + .split(',') + .join(arrayDelimiter) + )}` + ].join(`${delimiter}`) } } + const routerModes = ['history', 'hash'] const locations = (() => { const origin = 'https://a.b' @@ -59,11 +71,12 @@ describe('测试 stringify', () => { test('基本功能', () => { expect(stringify(query.obj)).toBe(query.str()) }) - test('自定义 equal & delimiter', () => { + test('自定义 equal & delimiter & arrayDelimiter', () => { const equal = '=' const delimiter = '&' - const str = query.str(equal, delimiter) - expect(stringify(query.obj, equal, delimiter)).toBe(str) + const arrayDelimiter = '$' + const str = query.str(equal, delimiter, arrayDelimiter) + expect(stringify(query.obj, equal, delimiter, arrayDelimiter)).toBe(str) }) })