react-view-router
Version:
react-view-router
106 lines (105 loc) • 3.61 kB
JavaScript
const encodeReserveRE = /[!'()*]/g;
const encodeReserveReplacer = c => '%' + c.charCodeAt(0).toString(16);
const commaRE = /%2C/g;
// fixed encodeURIComponent which is more conformant to RFC3986:
// - escapes [!'()*]
// - preserve commas
const encode = str => encodeURIComponent(str).replace(encodeReserveRE, encodeReserveReplacer).replace(commaRE, ',');
const decode = decodeURIComponent;
function parseQuery(query, props = {}) {
const res = {};
query = query.trim().replace(/^(\?|#|&)/, '');
if (!query) {
return res;
}
query.split('&').forEach(param => {
const parts = param.replace(/\+/g, ' ').split('=');
const key = decode(parts.shift() || '');
let val = parts.length > 0 ? decode(parts.join('=')) : null;
if (val === 'true') val = true;else if (val === 'false') val = false;else if (val === 'null') val = null;else if (val === 'undefined') val = undefined;else if (val === 'NaN') val = NaN;else if ((val || '').indexOf('[object ') !== 0 && /^(\{.*\})|(\[.*\])$/.test(val)) {
try {
val = JSON.parse(val);
} catch (e) {/* empty */}
} else if (props[key]) {
try {
val = props[key](val, key, query);
} catch (e) {
console.error(e);
}
}
if (res[key] === undefined) {
res[key] = val;
} else if (Array.isArray(res[key])) {
res[key].push(val);
} else {
res[key] = [res[key], val];
}
});
return Object.keys(res).sort().reduce((p, key) => {
p[key] = res[key];
return p;
}, {});
}
function stringifyQuery(obj, prefix = '?') {
const res = obj ? Object.keys(obj).sort().map(key => {
let val = obj[key];
if (val === undefined) return '';
if (val === null || val === undefined) return encode(key);
if (Array.isArray(val)) {
const result = [];
val.forEach(val2 => {
if (val2 === undefined) return;
if (val2 === null) {
result.push(encode(key));
} else {
if (typeof val2 === 'object') val2 = JSON.stringify(val2);
result.push(encode(key) + '=' + encode(val2));
}
});
return result.join('&');
}
if (typeof val === 'object') val = JSON.stringify(val);
return encode(key) + '=' + encode(val);
}).filter(x => x.length > 0).join('&') : null;
return res ? `${prefix}${res}` : '';
}
export { parseQuery, stringifyQuery };
const config = {
_parseQuery: parseQuery,
_stringifyQuery: stringifyQuery,
inheritProps: false,
zIndexStart: 0,
zIndexStep: 1,
get parseQuery() {
return this._parseQuery;
},
get stringifyQuery() {
return this._stringifyQuery;
},
createMergeStrategie(router) {
return function routeMergeStrategie(parent, child, vm) {
if (vm._isVuelikeRoot) {
if (router.Apps.some(App => vm instanceof App)) {
router.apps.push(vm);
vm.$on('componentDidUnmount', () => {
const idx = router.apps.indexOf(vm);
if (~idx) router.apps.splice(idx, 1);
});
}
return parent;
}
vm.$computed(vm, '$route', function () {
return this.$root ? this.$root.$route : null;
});
vm.$computed(vm, '$routeIndex', function () {
if (this._routeIndex !== undefined) return this._routeIndex;
const routeView = router.getHostRouterView(this, v => !v._isVuelikeRoot);
return this._routeIndex = routeView ? routeView.state.depth : -1;
});
vm.$computed(vm, '$matchedRoute', function () {
return this.$route && this.$route.matched[this.$routeIndex] || null;
});
};
}
};
export default config;