src/qsman.js
import {
getUrlQueryString,
parseQueryString,
stripUrlQueryString,
getUrlHash
} from './util.js';
/**
* 解析和维护 URL 上的参数, 接口设计参考 `URLSearchParams`
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
*/
class QsMan {
/**
* @param {string} url
*/
constructor(url) {
this._url = url || '';
// 解析 URL 已有的 querystring
this._queryStringKvs = parseQueryString(getUrlQueryString(this._url));
}
/**
* 追加 URL 参数
*
* @param {string | object} queryString
* @return {object} this
*/
append(queryString) {
var queryStringKvs = parseQueryString(queryString);
this._queryStringKvs = this._queryStringKvs.concat(queryStringKvs);
return this;
}
/**
* 获取找到的第一个参数值
*
* @param {string} name 要获取的参数名
* @return {string | undefined}
*/
get(name) {
return this.getAll(name)[0];
}
/**
* 获取参数的所有值
*
* @param {string} name 要获取的参数名
* @return {Array<string>}
*/
getAll(name) {
return this._queryStringKvs.filter(function(kv) {
return kv.key === name;
}).map(function(kv) {
return kv.value;
});
}
/**
* 设置参数值
*
* @param {string} name
* @param {string | Array<string>} value
* @return {object} this
*/
set(name, value) {
var kvMap = {};
kvMap[name] = value;
// 解析出 value 值
var valueQueryStringKvs = parseQueryString(kvMap);
var found = this._queryStringKvs.filter(function(kv) {
return kv.key === name;
});
if (found.length > 0) {
// 记录要设置的参数的位置
var kvIndex = this._queryStringKvs.indexOf(found[0]);
// 先删除再插入
this.delete(name);
// 在追加的位置切一刀(将需要替换的元素排除掉)
var left = this._queryStringKvs.slice(0, kvIndex);
var right = this._queryStringKvs.slice(kvIndex + 1);
// 在左边追加参数
for (var i = 0, length = valueQueryStringKvs.length; i < length; i++) {
left.push(valueQueryStringKvs[i]);
}
this._queryStringKvs = left.concat(right);
} else {
this.append(kvMap);
}
return this;
}
/**
* 是否有某个参数
*
* @param {string} name
* @return {boolean}
*/
has(name) {
return this._queryStringKvs.filter(function(kv) {
return kv.key === name;
}).length > 0;
}
/**
* 删除某个参数
*
* @param {string} name
* @return {object} this
*/
delete(name) {
var queryStringKvs = this._queryStringKvs;
queryStringKvs.filter(function(kv) {
return kv.key === name;
}).forEach(function(item) {
var kvIndex = queryStringKvs.indexOf(item);
queryStringKvs.splice(kvIndex, 1);
});
return this;
}
/**
* 获取所有参数的名称
*
* @return {Array<string>}
*/
keys() {
return this._queryStringKvs.reduce(function(keys, kv) {
if (keys.indexOf(kv.key) === -1) {
keys.push(kv.key);
}
return keys;
}, []);
}
/**
* 对参数进行升序排序
*
* @return {object} this
*/
sort() {
this._queryStringKvs.sort(function(kv1, kv2) {
var compareResult;
if (kv1.key > kv2.key) {
compareResult = 1;
} else if (kv1.key < kv2.key) {
compareResult = -1;
} else {
compareResult = 0;
}
return compareResult;
});
return this;
}
/**
* 拼装 URL
*
* @param {boolean} [includeEmptyStringValue=true] 是否包含空字符串参数值的参数
* @return {string}
*/
toString(includeEmptyStringValue = true) {
var url = '';
var queryStringKvs = this._queryStringKvs;
// 排除空字符串的 KEY
queryStringKvs = queryStringKvs.filter(function(kv) {
return kv.key !== '';
});
if (!includeEmptyStringValue) {
queryStringKvs = queryStringKvs.filter(function(kv) {
return kv.value !== '';
});
}
var queryString = queryStringKvs.map(function(kv) {
var key = encodeURIComponent(kv.key);
var value = encodeURIComponent(kv.value);
return key + '=' + value;
}).join('&');
// 重组 URL
url = stripUrlQueryString(this._url);
if (queryString) {
url = url ? url + '?' + queryString : queryString;
}
var hash = getUrlHash(this._url);
if (hash) {
url = url + '#' + hash;
}
return url;
}
/**
* 替换 URL 参数
*
* @param {string | object} queryString
* @return {object} this
*/
replace(queryString) {
var queryStringKvs = parseQueryString(queryString);
for (var i = 0, length = queryStringKvs.length; i < length; i++) {
this.delete(queryStringKvs[i].key);
}
this.append(queryString);
return this;
}
/**
* 获取参数对象
*
* @return {object} 返回包含了所有参数的对象, 例如: `{key1: 'value1', key2: 'value2', key3: ['value3', 'value4']}`
*/
getObject() {
return this._queryStringKvs.reduce(function(object, kv) {
var key = kv.key;
var value = kv.value;
var objectValue = object[key];
if (typeof objectValue === 'undefined') {
object[key] = value;
} else {
if (Object.prototype.toString.apply(objectValue) === '[object Array]') { // 找到多个
objectValue.push(value);
} else {
object[key] = [objectValue, value];
}
}
return object;
}, {});
}
}
export default QsMan;