Vue Router использует механизм маршрутизации на основе URL, и одним
из ключевых аспектов является работа с параметрами запроса (query
parameters). По умолчанию библиотека предоставляет стандартный парсер
для query-параметров, однако иногда возникает необходимость создать
кастомную функцию parseQuery, чтобы
управлять процессом разбора строки запроса по своим правилам.
Функция parseQuery отвечает за преобразование строки
запроса из URL в объект JavaScript. Стандартный механизм Vue Router
разбивает URL вида:
/products?category=books&page=2
в объект:
{
category: 'books',
page: '2'
}
Кастомная функция позволяет полностью контролировать этот процесс: менять формат значений, обрабатывать массивы, конвертировать числа, логировать ошибки и даже поддерживать сложные вложенные структуры.
Кастомная parseQuery должна иметь сигнатуру:
type ParseQuery = (query: string) => Record
где query — это строка после символа ? в
URL, а функция возвращает объект с ключами и значениями. Важно, чтобы
функция корректно обрабатывала пустую строку и специальные символы,
такие как +, %20, &,
=.
function parseQuery(queryString) {
const query = Object.create(null);
if (!queryString) return query;
queryString
.replace(/^\?/, '')
.split('&')
.forEach(pair => {
const [key, value] = pair.split('=').map(decodeURIComponent);
if (key) query[key] = value ?? '';
});
return query;
}
Разбор кода:
replace(/^\?/, '') удаляет ведущий символ
?, если он присутствует.split('&') делит строку на отдельные пары
ключ-значение.decodeURIComponent декодирует URL-кодированные
символы.value ?? '' обеспечивает наличие пустой строки, если
значение отсутствует.Стандартный парсер Vue Router не поддерживает вложенные структуры по
умолчанию. Кастомная функция может это исправить, используя соглашения
вроде items[]=1&items[]=2 для массивов или
user[name]=John&user[age]=30 для объектов.
Пример:
function parseQuery(queryString) {
const query = {};
if (!queryString) return query;
queryString
.replace(/^\?/, '')
.split('&')
.forEach(pair => {
let [key, value] = pair.split('=').map(decodeURIComponent);
if (!key) return;
// Обработка массивов
if (key.endsWith('[]')) {
key = key.slice(0, -2);
if (!query[key]) query[key] = [];
query[key].push(value ?? '');
return;
}
// Обработка вложенных объектов
const nestedMatch = key.match(/^(\w+)\[(\w+)\]$/);
if (nestedMatch) {
const parent = nestedMatch[1];
const child = nestedMatch[2];
if (!query[parent]) query[parent] = {};
query[parent][child] = value ?? '';
return;
}
query[key] = value ?? '';
});
return query;
}
Эта реализация позволяет:
[].ключ[подключ].При создании экземпляра маршрутизатора можно указать собственный парсер:
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/products', component: Products },
{ path: '/users', component: Users }
],
parseQuery(queryString) {
return parseQuery(queryString); // наша кастомная функция
}
});
Теперь все переходы по URL будут использовать кастомную логику разбора query-параметров.
'true' и 'false' в
булевы значения, числа в Number, а пустые строки в
null.decodeURIComponent, чтобы предотвратить ошибки при
неправильном кодировании URL.[] и [ключ] для
структурирования данных.URLSearchParams) и сравнивать результаты
с кастомным парсером.function parseQuery(queryString) {
const query = {};
if (!queryString) return query;
queryString
.replace(/^\?/, '')
.split('&')
.forEach(pair => {
let [key, value] = pair.split('=').map(decodeURIComponent);
if (!key) return;
// Конвертация типов
if (value === 'true') value = true;
else if (value === 'false') value = false;
else if (!isNaN(value) && value !== '') value = Number(value);
// Обработка массивов
if (key.endsWith('[]')) {
key = key.slice(0, -2);
if (!query[key]) query[key] = [];
query[key].push(value);
return;
}
query[key] = value;
});
return query;
}
Эта версия позволяет сразу получать типизированные значения без дополнительной обработки после парсинга.