Модифікація рядка запиту без перезавантаження сторінки


114

Я створюю фотогалерею і хотів би мати можливість змінити рядок запиту та назву під час перегляду фотографій.

Поведінка, яку я шукаю, часто спостерігається з деякими реалізаціями безперервної / нескінченної сторінки, де під час прокрутки вниз рядок запиту збільшується на номер сторінки ( http://x.com?page=4 ) тощо. Це повинно бути теоретично просто, але я хотів би щось безпечне для основних браузерів.

Я знайшов цю чудову посаду і намагався наслідувати приклад window.history.pushstate, але це, здається, не працює для мене. І я не впевнений, чи ідеально це, бо мені не дуже важливо змінювати історію браузера.

Я просто хочу мати можливість пропонувати можливість закладки фотографій, що переглядаються в даний момент, не перезавантажуючи сторінку щоразу, коли фотографія змінюється.

Ось приклад нескінченної сторінки, яка змінює рядок запиту: http://tumbledry.org/

UPDATE знайшов цей метод:

window.location.href = window.location.href + '#abc';

це, здається, працює для мене, але я перебуваю на новому хромі .. це, мабуть, спричинить деякі проблеми зі старими браузерами?


Чи можете ви розмістити посилання на якийсь приклад веб-сайт, який динамічно оновлює рядок запитів? Я не думаю, що це можна зробити, але ви можете змінити значення хешу і цього може бути достатньо, щоб отримати те, що ви хочете.
Pointy



Можливий дублікат Чому нова веб-Dropbox може змінити URL-адресу без оновлення сторінки? і три питання позначені як дублікат
Квентін

@Quentin. Ви можете мати лише один ближчий голос ...:)
gdoron підтримує Моніку

Відповіді:


185

Якщо ви шукаєте модифікацію Hash, ваше рішення працює нормально. Однак якщо ви хочете змінити запит, ви можете використовувати pushState, як ви вже говорили. Ось приклад, який може допомогти вам правильно його реалізувати. Я тестував, і це працювало чудово:

if (history.pushState) {
    var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?myNewUrlQuery=1';
    window.history.pushState({path:newurl},'',newurl);
}

Він не перезавантажує сторінку, але лише дозволяє змінити URL-запит. Ви не зможете змінити значення протоколу або хосту. І звичайно, що для цього потрібні сучасні браузери, які можуть обробляти API історії HTML5.

Для отримання додаткової інформації:

http://diveintohtml5.info/history.html

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history


6
Я вважаю , що ви можете скоротити window.location.protocol + '//' + window.location.hostпросто: window.location.origin.
Гаррет

4
Крім того, для отримання додаткової частини інформації також працюють відносні шляхи history.pushState(). Фактичний stateаргумент також не потрібен. І те й інше означає, що ви можете зробити щось просте, наприклад, history.pushState(null, '', '/foo?bar=true')якщо ваша нова URL-адреса знаходиться на тому ж хості / порті.
Blaskovicz

23
Зауважте, що якщо ви не хочете, щоб новий стан з’являвся в історії браузера, ви можете використовувати history.replaceState()ті самі аргументи.
Блакус

6
USE history.replaceState () в іншому випадку потрібно двічі натиснути кнопку НАЗАД у вашому браузері
Женя

4
У сучасних браузерах ви просто можете:if (window.history.pushState) { const newURL = new URL(window.location.href); newURL.search = '?myNewUrlQuery=1'; window.history.pushState({ path: newURL.href }, '', newURL.href); }
Аллан Баптиста,

8

Спираючись на відповідь Фабіо, я створив дві функції, які, мабуть, будуть корисні для кожного, хто натрапив на це питання. За допомогою цих двох функцій ви можете зателефонувати insertParam()за допомогою ключа та значення в якості аргументу. Він або додасть параметр URL, або, якщо параметр запиту вже існує з тим самим ключем, він змінить цей параметр на нове значення:

//function to remove query params from a URL
function removeURLParameter(url, parameter) {
    //better to use l.search if you have a location/link object
    var urlparts= url.split('?');   
    if (urlparts.length>=2) {

        var prefix= encodeURIComponent(parameter)+'=';
        var pars= urlparts[1].split(/[&;]/g);

        //reverse iteration as may be destructive
        for (var i= pars.length; i-- > 0;) {    
            //idiom for string.startsWith
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {  
                pars.splice(i, 1);
            }
        }

        url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
        return url;
    } else {
        return url;
    }
}

//function to add/update query params
function insertParam(key, value) {
    if (history.pushState) {
        // var newurl = window.location.protocol + "//" + window.location.host + search.pathname + '?myNewUrlQuery=1';
        var currentUrlWithOutHash = window.location.origin + window.location.pathname + window.location.search;
        var hash = window.location.hash
        //remove any param for the same key
        var currentUrlWithOutHash = removeURLParameter(currentUrlWithOutHash, key);

        //figure out if we need to add the param with a ? or a &
        var queryStart;
        if(currentUrlWithOutHash.indexOf('?') !== -1){
            queryStart = '&';
        } else {
            queryStart = '?';
        }

        var newurl = currentUrlWithOutHash + queryStart + key + '=' + value + hash
        window.history.pushState({path:newurl},'',newurl);
    }
}

наскільки ваші функції кращі, ніж new URLSearchParams()із вбудованими методами, як встановити та видалити ? в будь-якому випадку ми повинні поставити це в історію зhistory.pushState()
AlexNikonov

1
new URLSearchParams()не підтримується жодними версіями IE
jmona789

Дякую @ jmona789, це прекрасно працювало для мене і саме те, що я шукав
mknopf

7

Я з великим успіхом використовував таку бібліотеку JavaScript:

https://github.com/balupton/jquery-history

Він підтримує API історії HTML5, а також резервний метод (використовуючи #) для старих браузерів.

Ця бібліотека по суті є поліфоном навколо "history.pushState".


приголомшливий! ти тестував це з усіма браузерами ??
Sonic Soul

Моя реалізація була протестована в IE7 +, Firefox 3.6+, Safari 5 та Chrome 16+. Можливо, він працює і з іншими браузерами, але я не мав жодних скарг у кількох системах, розгорнутих за його допомогою.
Ян Ньюсон

чудовий. так що зараз .. просто ставити # замість & при написанні до window.location.href працює для мене. оскільки він не перезавантажує сторінку. Я впевнений, що колись він зламається, я перевіряю його в IE .. в цей момент я піду з бібліотекою, яку ви запропонували. спасибі
Sonic Soul

Метод # хороший тим, що має дуже широку підтримку браузера. Все може ускладнитися, коли вам потрібно включити цю інформацію до запитів на сервер, оскільки браузер не надсилає # частину URL-адреси. Існують способи, які включають бібліотеку, на яку я посилався. Крім того, використання API історії HTML5 допомагає зменшити загальну кількість ваших URL-адрес і вимагає менше роботи клієнта для відновлення стану.
Ян Ньюсон

Метод # також є проблематичним для спільного використання соціальних медіа; Twitter, Facebook та, можливо, інші не дуже добре позначаються прив’язними тегами при створенні попереднього перегляду або посилань на спільну публікацію.
mirth23

5

Я хочу покращити відповідь Фабіо і створити функцію, яка додає спеціальний ключ до рядка URL-адреси, не завантажуючи сторінку.

function insertUrlParam(key, value) {
    if (history.pushState) {
        let searchParams = new URLSearchParams(window.location.search);
        searchParams.set(key, value);
        let newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams.toString();
        window.history.pushState({path: newurl}, '', newurl);
    }
}

0

Тоді API історії саме те, що ви шукаєте. Якщо ви також хочете підтримувати застарілі веб-переглядачі, то знайдіть бібліотеку, яка повертається до маніпулювання хеш-тегом URL-адреси, якщо браузер не надає API історії.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.