Питання Як я можу отримати значення рядка запиту в JavaScript?


Є спосіб вилучення плагіна рядок запиту значення за допомогою jQuery (чи без нього)?

Якщо так, то як? Якщо ні, чи існує плагін, який може це зробити?


2703


походження


Я використовую плагін getUrlParam описаний в jQuery-Plugin - getUrlParam (версія 2). - coma
А. звичайний javascript рішення без RegEx: css-tricks.com/snippets/javascript/get-url-variables - Lorenzo Polidori
Незважаючи на те, що найкраще рішення цього питання заслуговує на популярність через відмінне спостереження, що jQuery не потрібен, його метод створення нових регулярних виразів і повторна обробка рядка запитів для кожного потрібного параметра надзвичайно неефективна. Набагато більш ефективні (і універсальні) рішення існують протягом тривалого часу, наприклад, в рамках цієї статті, перевиданої тут: htmlgoodies.com/beyond/javascript/article.php/11877_3755006_3/... - Joseph Myers
можливий дублікат Рядок запиту JavaScript
Джозеф, "відмінне спостереження, що jQuery не потрібні"? Звичайно, це не потрібно. Все, що робить у jQuery, використовує JavaScript. Люди не використовують jQuery, тому що це робить те, що JavaScript не може зробити. Точка jQuery - це зручність. - Vladimir Kornea


Відповіді:


Для цього вам не потрібна jQuery. Ви можете використовувати лише один чистий JavaScript:

function getParameterByName(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

Використання:

// query string: ?foo=lorem&bar=&baz
var foo = getParameterByName('foo'); // "lorem"
var bar = getParameterByName('bar'); // "" (present with empty value)
var baz = getParameterByName('baz'); // "" (present with no value)
var qux = getParameterByName('qux'); // null (absent)


Примітка: якщо параметр присутній кілька разів (?foo=lorem&foo=ipsum), ви отримаєте перше значення (lorem) Про цей стандарт не існує, а використання не збігається, наприклад, це питання: Авторитетна позиція дублікатів ключів запиту HTTP GET.
ПРИМІТКА. Функція чутлива до регістру. Якщо ви віддаєте перевагу імені параметра, нечутливого до регістру додати "I" модифікатор до RegExp


Це оновлення на основі нового URLSearchParams специфікації щоб досягти такого ж результату більш лаконічно. Подивіться відповідь під назвою "URLSearchParams"нижче.


7025



Ніхто не каже, що це не може бути зроблено з чистого Javascript. Якщо ви вже використовуєте jQuery, і jQuery має функцію, щоб зробити це, тоді було б сенс використовувати jQuery, а не винаходити колесо за допомогою нової функції. - Cerin
Як працює ця функція http://www.mysite.com/index.php?x=x1&x=x2&x=x3 Значення поля x неоднозначно. - dpp
це також не справляється багатозначні клавіші, які також абсолютно законні. - hurrymaplelad
Чому ви використовуєте для цього регулярний вираз? - Ry-♦
Для запиту строк дії ?mykey=0&m.+key=1, зателефонувавши getParameterByName("m.+key") повернеться 0 замість 1. Вам потрібно уникнути метасимволів регулярного виразу name перед тим, як створити свій регулярний вираз. І вам потрібно лише подзвонити .replace() один раз, використовуючи глобальний прапорець і використовуючи "\\$&" як замінне вираз. Ви повинні шукати location.search замість location.href. Відповідь з більш ніж 400 upvotes повинна враховувати ці деталі. - gilly3


Деякі рішення, опубліковані тут, неефективні. Повторюючи пошук за регулярним виразом кожного разу, коли скрипту потрібно отримати доступ до параметра, цілком непотрібно, достатньо однієї функції для розбиття параметрів на об'єкт стилю асоціативного масиву. Якщо ви не працюєте з API HTML 5 History, це необхідно лише раз на завантаження сторінки. Інші пропозиції також неправильно декодують URL-адресу.

var urlParams;
(window.onpopstate = function () {
    var match,
        pl     = /\+/g,  // Regex for replacing addition symbol with a space
        search = /([^&=]+)=?([^&]*)/g,
        decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
        query  = window.Місцезнаходження.search.підрядка(1);

    urlParams = {};
    while (match = search.виконувати(query))
       urlParams[decode(match[1])] = decode(match[2]);
})();

Приклад строку запиту:

?i=main&mode=front&sid=de8d49b78a85a322c4155015fdce22c4&enc=+Hello%20&empty

Результат:

 urlParams = {
    enc: " Hello ",
    i: "main",
    mode: "front",
    sid: "de8d49b78a85a322c4155015fdce22c4",
    empty: ""
}

alert(urlParams["mode"]);
// -> "front"

alert("empty" in urlParams);
// -> true

Це може бути легко покращено для обробки рядків запиту в стилі масиву. Прикладом цього є тут, але оскільки параметри стилю масиву не визначені в RFC 3986 Я не буду забруднювати цю відповідь вихідним кодом. Для тих, хто зацікавлений в "забрудненій" версії, подивіться на відповідь campbeln.

Крім того, як зазначено в коментарі, ; є законним розмежуванням для key=value пари Для цього буде потрібно складніший регулярний вираз ; або &, який, на мою думку, непотрібний, тому що це рідко ; використовується, і я б сказав, ще менш ймовірно, що обидва будуть використовуватися. Якщо вам потрібно підтримати ; замість &, просто помістіть їх у регулярний вираз.


  Якщо ви використовуєте мову попередньої обробки на стороні сервера, можливо, вам знадобиться використовувати свої власні функції JSON, щоб зробити вашу важливу роботу. Наприклад, у PHP ви можете написати:

<script>var urlParams = <?php echo json_encode($_GET, JSON_HEX_TAG);?>;</script>

Набагато простіше!


1627



якщо ви робите сильно додаток ajax'd, то ви можете використовувати хеш (#) для "включення кнопки зворотного зв'язку" ... у цьому випадку строка запиту буде змінюватися весь час (див., як це робить "facebook"). .. хоча ці рішення ігнорують речі, що відбуваються після # анвейсу ... - Nick Franceschina
@Nick: все, що після хешу знаходиться в window.location.hash власність, яка відрізняється від window.location.search власність Якщо хеш змінюється, воно взагалі не впливає на строку запиту. - Andy E
Не забувайте про це ; це юридичний розбіжник для GET key=value пари Це рідко, але це потрібно 5 секунд для реалізації. - alex
Для чесності, специфічний формат для рядка запиту не визначається RFC3986. ?a=b&c=d це звичайна, а також рекомендація W3C для веб-форм, але специфікація URI просто визначає query = *( pchar / "/" / "?" ). - Matthew Gilliard
Для тих з нас, використовуючи досить жорсткий набір JSHint заміни while(match = search.exec(query)) з while((match = search.exec(query)) !== null) - craigts


ES2015 (ES6)

getQueryStringParams = query => {
    return query
        ? (/^[?#]/.test(query) ? query.slice(1) : query)
            .split('&')
            .reduce((params, param) => {
                    let [key, value] = param.split('=');
                    params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
                    return params;
                }, {}
            )
        : {}
};

Без jQuery

var qs = (function(a) {
    if (a == "") return {};
    var b = {};
    for (var i = 0; i < a.length; ++i)
    {
        var p=a[i].split('=', 2);
        if (p.length == 1)
            b[p[0]] = "";
        else
            b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
    }
    return b;
})(window.location.search.substr(1).split('&'));

З URL, як ?topic=123&name=query+string, повернеться наступне:

qs["topic"];    // 123
qs["name"];     // query string
qs["nothere"];  // undefined (object)

Метод Google

Роздираючи код Google, я знайшов метод, який вони використовують: getUrlParameters

function (b) {
    var c = typeof b === "undefined";
    if (a !== h && c) return a;
    for (var d = {}, b = b || k[B][vb], e = b[p]("?"), f = b[p]("#"), b = (f === -1 ? b[Ya](e + 1) : [b[Ya](e + 1, f - e - 1), "&", b[Ya](f + 1)][K](""))[z]("&"), e = i.dd ? ia : unescape, f = 0, g = b[w]; f < g; ++f) {
        var l = b[f][p]("=");
        if (l !== -1) {
            var q = b[f][I](0, l),
                l = b[f][I](l + 1),
                l = l[Ca](/\+/g, " ");
            try {
                d[q] = e(l)
            } catch (A) {}
        }
    }
    c && (a = d);
    return d
}

Це заплутано, але це зрозуміло.

Вони починають шукати параметри на url з ? а також з хешу #. Тоді для кожного параметра вони розділяються на знак рівності b[f][p]("=") (що виглядає як indexOf, вони використовують позицію символу, щоб отримати ключ / значення). Розділяючи їх, вони перевіряють, чи має параметр значення, чи ні, якщо він зберігає значення d, інакше вони просто продовжують.

В кінці об'єкта d повертається, обробляючи втечу і + знак Цей об'єкт, як і моє, має таку саму поведінку.


Мій метод як jQuery плагін

(function($) {
    $.QueryString = (function(paramsArray) {
        let params = {};

        for (let i = 0; i < paramsArray.length; ++i)
        {
            let param = paramsArray[i]
                .split('=', 2);

            if (param.length !== 2)
                continue;

            params[param[0]] = decodeURIComponent(param[1].replace(/\+/g, " "));
        }

        return params;
    })(window.location.search.substr(1).split('&'))
})(jQuery);

Використання

//Get a param
$.QueryString.param
//-or-
$.QueryString["param"]
//This outputs something like...
//"val"

//Get all params as object
$.QueryString
//This outputs something like...
//Object { param: "val", param2: "val" }

//Set a param (only in the $.QueryString object, doesn't affect the browser's querystring)
$.QueryString.param = "newvalue"
//This doesn't output anything, it just updates the $.QueryString object

//Convert object into string suitable for url a querystring (Requires jQuery)
$.param($.QueryString)
//This outputs something like...
//"param=newvalue&param2=val"

//Update the url/querystring in the browser's location bar with the $.QueryString object
history.replaceState({}, '', "?" + $.param($.QueryString));
//-or-
history.pushState({}, '', "?" + $.param($.QueryString));

Тест продуктивності (метод розбиття на метод регулярного виразу) (jsPerf)

Код підготовки: методика декларування

Розбити тестовий код

var qs = window.GetQueryString(query);

var search = qs["q"];
var value = qs["value"];
var undef = qs["undefinedstring"];

Код тесту Regex

var search = window.getParameterByName("q");
var value = window.getParameterByName("value");
var undef = window.getParameterByName("undefinedstring");

Тестування в Firefox 4.0 x86 на Windows Server 2008 R2 / 7 x64

  • Спліт метод: Найшвидший - 144 780 ± 2,17%
  • Метод регулярного виразу: 13 891 ± 0,85% | 90% повільніше

1193



Це також хороший підхід, розщеплення рядків замість використання регулярних виразів. Варто зазначити кілька речей, хоча :-) 1. unescape є застарілою функцією і замінюється на decodeURIComponent(), зверніть увагу, що жодна з цих функцій не буде правильно декодувати a + до космічного персонажа. 2. Ви повинні оголосити результат як об'єкт, а не масив, тому що JavaScript не має асоціативних масивів, як таке, і масив, який ви оголошуєте, розглядається як об'єкт, в будь-якому разі присвоюючи йому названі властивості. - Andy E
Цікаво, чому ви створили цей плагін jQuery, коли він не має жодного коду jQuery? - zachleat
@zachleat, якщо у вас немає структури, ваші функції будуть просто розповсюджуватися по коду. Якщо ви поширюєте jQuery, ви матимете можливості для своїх функцій, воно не буде плавати навколо де-небудь у вашому коді. Я думаю, що це єдина причина. - BrunoLM
Ось версія jQuery налаштований для передачі JSLint (принаймні, півроку ціль JSLint.com 2011-06-15). Переважно просто переміщення речей навколо, щоб заспокоїти The Crockford. - patridge
Як поскаржився @BenjaminGruenbaum, я також не бачу точку в порівнянні результатів аналізу URL-адреси. Якщо це було зроблено в ізоморфному модулі JavaScript, який можна викликати з вузла, скажімо, розділити журнали, а потім - так. Але використовувати його для вилучення параметрів URL з window.location робить будь-які проблеми щодо продуктивності рутинним, оскільки клієнт, який здійснює навігацію по URL, набагато дорожче. - Dan Dascalescu


Покращена версія Відповідь Артема Барґера:

function getParameterByName(name) {
    var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}

Для отримання додаткової інформації про вдосконалення див. http://james.padolsey.com/javascript/bujs-1-getparameterbyname/


636



Якщо ви хочете скоротити його трохи більше, ви можете позбутися умовності трійкового та замінити його трохи короткого замикання на останньому рядку - return match && decodeURIComponent(match[1].replace(/\+/g, ' '));. - Andy E
Це повертається null якщо за параметром не вказано '='. Ви можете додати if (!RegExp('[?&]'+name+'(&.*)?$').exec(window.location.search)) return false; щоб він повернувся boolean false якщо параметр там взагалі не існує. - commonpike
Я хотів би використовувати new префікс при створенні регулярного виразу: var match = new RegExp('... - Patrick Berkeley
IE11 помилка: IE вирішує приєднати повернене значення за допомогою символу ASCII 8206 (hex: 200E - символ "зліва направо"). Я витратив більше 6 годин на пошук цього! терапевтична вентиляція .... щоб виправити, прикріпити до кінця останнього рядка: .replace('\u200E', '') - JayRO-GreyBeard
У chrome на Mac, принаймні (можливо, і в інших браузерах) останнє значення отримало '/' додається. Тому я змінив регулярний вираз, щоб ігнорувати його. var results = new RegExp('[\\?&]' + name + '=([^&#/]*)').exec(url); - CaseyB


URLSearchParams

Firefox 44+, Opera 36+, Edge 17+, Safari 10.3+ і Chrome 49+ підтримують URLSearchParams API:

Існує google-запропонований URLsearchParams polyfill для стабільних версій IE.

Він не стандартизований W3C, але це життєвий стандарт WhatWG.

Ви можете використовувати його на місці, але потрібно видалити ? знак питання (наприклад, з .slice(1)):

let params = new URLSearchParams(location.search.slice(1));

або

let params = (new URL(location)).searchParams;

Або, звичайно ж, будь-яка URL-адреса:

let url = new URL('https://example.com?foo=1&bar=2');
let params = new URLSearchParams(url.search.slice(1));

Ви також можете отримати параметри за допомогою стенограми .searchParams властивість об'єкту URL-адреси, як це:

let params = new URL('https://example.com?foo=1&bar=2').searchParams;
params.get('foo'); // "1"
params.get('bar'); // "2" 

Ви читаєте / встановлюєте параметри через get(KEY), set(KEY, VALUE), append(KEY, VALUE) API Ви також можете послідовно переглядати всі цінності for (let p of params) {}.

А. еталонна реалізація і a зразок сторінки доступні для аудиту та тестування.


482



IE все одно пропускає ... не те, що я використовую це :( - mlt
Ці два downvoters, ймовірно, пропустили (як я це зробив) той факт, що ви повинні використовувати .get замість просто . - Nakilon
Вам насправді не потрібно slice(1) на .search, ви можете використовувати його безпосередньо. URLSearchParams може займатися провідним ?. - Jason C
Будь ласка голосувати для цього помилка зафіксувати Це дозволить команді Edge знати, що є інтерес! - styfle
Краща відповідь. Нарешті, хтось запропонував рідний підхід. Дякую - Green


Ще одна рекомендація. Плагін Пухлина дозволяє отримувати всі частини URL-адреси, включаючи якоря, хост і т. д.

Він може використовуватися з або без jQuery.

Використання дуже просте і класно:

var url = $.url('http://allmarkedup.com/folder/dir/index.html?item=value'); // jQuery version
var url = purl('http://allmarkedup.com/folder/dir/index.html?item=value'); // plain JS version
url.attr('protocol'); // returns 'http'
url.attr('path'); // returns '/folder/dir/index.html'

Однак, станом на 11 листопада 2014 року, Purl більше не підтримується, і автор рекомендує використовувати URI.js замість цього. Плагін jQuery відрізняється тим, що він зосереджений на елементах - для використання з рядками просто використовуйте URI безпосередньо, з або без jQuery. Подібний код буде виглядати як такий, більш повні документи тут:

var url = new URI('http://allmarkedup.com/folder/dir/index.html?item=value'); // plain JS version
url.protocol(); // returns 'http'
url.path(); // returns '/folder/dir/index.html'

394



Починаючи з написання кульок більше не підтримується, і попередній супроводжуючий пропонує uri.js - Dan Pantry


тл; др

Швидкий, повне рішення, який обробляє багатозначні ключі і закодовані символи.

var qd = {};
if (location.search) location.search.substr(1).split("&").forEach(function(item) {var s = item.split("="), k = s[0], v = s[1] && decodeURIComponent(s[1]); (qd[k] = qd[k] || []).push(v)})

//using ES6   (23 characters cooler)
var qd = {};
if (location.search) location.search.substr(1).split`&`.forEach(item => {let [k,v] = item.split`=`; v = v && decodeURIComponent(v); (qd[k] = qd[k] || []).push(v)})
Багаторядний:
var qd = {};
if (location.search) location.search.substr(1).split("&").forEach(function(item) {
    var s = item.split("="),
        k = s[0],
        v = s[1] && decodeURIComponent(s[1]); //  null-coalescing / short-circuit
    //(k in qd) ? qd[k].push(v) : qd[k] = [v]
    (qd[k] = qd[k] || []).push(v) // null-coalescing / short-circuit
})

Що це все, цей код ...
"нуль-коалессінг", оцінка короткого замикання
ES6 Завдання з перекладу, Стрілка функції, Шаблонні рядки

Приклад:
"?a=1&b=0&c=3&d&e&a=5&a=t%20e%20x%20t&e=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dståle%26car%3Dsaab"
> qd
a: ["1", "5", "t e x t"]
b: ["0"]
c: ["3"]
d: [undefined]
e: [undefined, "http://w3schools.com/my test.asp?name=ståle&car=saab"]

> qd.a[1]    // "5"
> qd["a"][1] // "5"



Детальніше ... про рішення Vanilla JavaScript.

Для доступу до різних частин URL-адреси використовуйте location.(search|hash)

Найпростіший (манекен) рішення

var queryDict = {};
location.search.substr(1).split("&").forEach(function(item) {queryDict[item.split("=")[0]] = item.split("=")[1]})
  • Ручки порожні ключі правильно
  • Перевизначення багато клавіш з останній Знайдено значення.
"?a=1&b=0&c=3&d&e&a=5"
> queryDict
a: "5"
b: "0"
c: "3"
d: undefined
e: undefined

Багатозначні клавіші

Проста перевірка ключа (item in dict) ? dict.item.push(val) : dict.item = [val]

var qd = {};
location.search.substr(1).split("&").forEach(function(item) {(item.split("=")[0] in qd) ? qd[item.split("=")[0]].push(item.split("=")[1]) : qd[item.split("=")[0]] = [item.split("=")[1]]})
  • Тепер повертається масиви замість цього.
  • Доступ до значень за допомогою qd.key[index] або qd[key][index]
> qd
a: ["1", "5"]
b: ["0"]
c: ["3"]
d: [undefined]
e: [undefined]

Закодовані символи?

Використовуйте decodeURIComponent() на другий або обидва розколюється

var qd = {};
location.search.substr(1).split("&").forEach(function(item) {var k = item.split("=")[0], v = decodeURIComponent(item.split("=")[1]); (k in qd) ? qd[k].push(v) : qd[k] = [v]})
Приклад:
"?a=1&b=0&c=3&d&e&a=5&a=t%20e%20x%20t&e=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dståle%26car%3Dsaab"
> qd
a: ["1", "5", "t e x t"]
b: ["0"]
c: ["3"]
d: ["undefined"]  // decodeURIComponent(undefined) returns "undefined" !!!*
e: ["undefined", "http://w3schools.com/my test.asp?name=ståle&car=saab"]



З коментарів

* !!! Будь ласка, зверніть увагу, що decodeURIComponent(undefined) повертає рядок "undefined". Рішення полягає в простому використанні &&, що гарантує це decodeURIComponent() не викликається на невизначені значення. (Див "повне рішення" у верхній частині.)

v = v && decodeURIComponent(v);


Якщо строка запиту порожня (location.search == ""), результат є дещо помилковим qd == {"": undefined}. Перед тим, як запустити функцію аналізу, пропонується перевірити рядок запиту:

if (location.search) location.search.substr(1).split("&").forEach(...)

217



Приємно Єдине, що я міг би змінити - це, якщо для ключа не більше одного значення, то немає потреби, щоб він масив. Використовуйте лише масив, якщо для кожного ключа більше одного значення. - Pavel Nikolov
@ Павел Ніколов Я думаю, що це може призвести до труднощів, які іноді призведуть до масиву, а іноді до вартості. Вам спочатку потрібно перевірити це, тепер ви перевіряєте лише довжину, тому що ви будете використовувати цикли для отримання цих значень у будь-якому випадку. Також це було найпростішим, але функціональним рішенням. - Qwerty
@twig не буде працювати в IE8 - sqram
Трохи згладжено для читабельності, зробленої в функції, і повторно використаний роздільний дзвінок: функція parseQueryString () (var qd = (); var (var) k = os [0]; var v = decodeURIComponent (parts [s] 1]); (k в qd)? Qd [k]. Push (v): qd [k] = [v,]}); повернути qd; } - Casey
decodeDocumentURI (undefined) повертає "undefined" замість undefined. Функціональний, але не дуже витончений патч: var qd = {}; location.search.substr(1).split("&").forEach( function(item) { var s = item.split("="), k = s[0], v; if(s.length>1) v = decodeURIComponent(s[1]); (k in qd) ? qd[k].push(v) : qd[k] = [v] }) - loop


Roshambo на сайті snipplr.com має простий сценарій, щоб досягти описаного в Отримати параметри URL-адреси за допомогою jQuery | Покращено. З його скриптом ви також можете легко витягнути потрібні параметри.

Ось суть:

$.urlParam = function(name, url) {
    if (!url) {
     url = window.location.href;
    }
    var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(url);
    if (!results) { 
        return undefined;
    }
    return results[1] || undefined;
}

Потім достатньо отримати параметри з рядка запиту.

Отже, якщо рядок URL / запиту був xyz.com/index.html?lang=de.

Просто дзвоніть var langval = $.urlParam('lang');, і у вас його є.

UZBEKJON також має чудовий допис в блозі Отримати параметри та значення URL-адреси за допомогою jQuery.


215



з jQuery здається, означає для простору імен функцію для об'єкта jQuery. Крім того, чому це недійсне значення 0? Звичайно, я міг би використовувати строгу перевірку рівності, але це не повинно бути null ? - alex
Згоден Вона працює так само, як звичайна посилання змінної javascript (за винятком, можливо, повернення невизначеною було б більш точним). - Isochronous
"ім'я" неправильно випущено, його просто вводять безпосередньо в RegExp. Це не вдається. Як і інші сказали, це неймовірно, що ці відповіді винаходять колесо і отримують стільки голосів, коли це потрібно реалізувати в добре перевіреній бібліотеці. - Triynko