Зберігати змінні між завантаженнями сторінок


96

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

Ось те, що я спробував:

  var clicked = false;

  $(document).ready(function() {

    $("input[type='submit'][value='Search']").attr("onclick", "form.act.value='detailSearch'; clicked = true;  return true;");

    if (clicked == true) {
      // show hidden fields
    } else {
      // don't show hidden fields
    }
  });

Будь-які пропозиції щодо того, що неправильно з цим кодом?


1
Я не думаю, що цього можна зробити без якогось сховища. Усі ваші змінні JS будуть очищені. Весь ваш обсяг буде перероблений.
Дейв Альперович

Чому б вам не розмістити більшу частину сторінки в "частковому" і не оновити це?
Дейв Альперович

Що таке часткове? На жаль, я цього не знаю.
Неофіл

Ви розглядали можливість подати форму через ajax та показати поля після подання?
dannyshaw

1
Чи можете ви детальніше пояснити, чому вам потрібно оновити сторінку? Якщо ми зможемо цього уникнути, ви зможете робити те, що хочете, якщо будете просто preventDefaultна submitзаході (замість того, що clickви використовуєте.)
Пелег

Відповіді:


205

Оскільки HTTP не має статусу, кожен раз, коли ви завантажуєте сторінку, він використовуватиме початкові значення того, що ви встановили в JavaScript. Ви не можете встановити глобальну змінну в JS і просто змусити це значення залишатися після завантаження сторінки знову.

Є кілька способів зберегти значення в іншому місці, щоб можна було ініціалізувати його при завантаженні за допомогою JavaScript


Рядок запиту

Під час надсилання форми за допомогою GETметоду URL-адреса оновлюється за допомогою рядка запиту ( ?parameter=value&something=42). Ви можете використати це, встановивши для поля введення у форму певне значення. Це буде найпростіший приклад:

<form method="GET">
    <input type="hidden" name="clicked" value="true" />
    <input type="submit" />
</form>

При початковому завантаженні сторінки рядок запиту не встановлюється. Коли ви подаєте цю форму, комбінація вхідних даних nameта valueкомбінація вхідних даних передаються у рядок запиту як clicked=true. Отже, коли сторінка знову завантажується за допомогою цього рядка запиту, ви можете перевірити, чи натиснуто кнопку.

Щоб прочитати ці дані, ви можете використовувати такий сценарій при завантаженні сторінки:

function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
        results = regex.exec(location.search);
    return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}

var clicked = getParameterByName('clicked');

( Джерело )

Можливість використовувати це залежить від того, як у даний час працює ваша форма; якщо ви вже використовуєте POST, це може бути проблематично.

Крім того, для більших наборів даних це менше, ніж оптимальне. Передача рядка не є великою проблемою, але для масивів та об’єктів даних вам слід використовувати веб-сховище або файли cookie. Хоча деталі дещо різняться між браузерами, практичне обмеження довжини URI становить близько 2000 символів


Веб-сховище

З введенням HTML5 ми також отримали веб-сховище, яке дозволяє зберігати інформацію в браузері при завантаженні сторінок. Існує localStorageможливість збереження даних протягом тривалого періоду (якщо користувач не видаляє їх вручну) і sessionStorageяка зберігає дані лише під час поточного сеансу перегляду. Останнє для вас тут корисно, оскільки ви не хочете, щоб "натиснуто" було встановлено в значення true, коли користувач повернеться пізніше.

Тут я встановив сховище для події натискання кнопки, але ви також можете прив'язати його до форми подання або чогось іншого.

$('input[type="submit"][value="Search"]').click(function() {
    sessionStorage.setItem('clicked', 'true');
});

Потім, завантажуючи сторінку, ви можете перевірити, чи встановлена ​​вона, використовуючи це:

var clicked = sessionStorage.getItem('clicked');

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

sessionStorage.removeItem('clicked');

Якщо ви хочете зберегти об'єкт або масив JS, вам слід перетворити це на рядок. Відповідно до специфікації, має бути можливим збереження інших типів даних, але це ще неправильно реалізовано в браузерах.

//set
localStorage.setItem('myObject', JSON.stringify(myObject));

//get
var myObject = JSON.parse(localStorage.getItem('myObject'));

Підтримка браузера є чудовою, тому ви повинні бути впевнені у використанні цього, якщо вам не потрібно підтримувати справді старі / неясні браузери. Веб-сховище - це майбутнє.


Печиво

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

Ви вже використовуєте jQuery, що робить налаштування файлів cookie досить простим. Знову ж таки, я використовую clickподію тут, але міг би бути використаний де завгодно.

$('input[type="submit"][value="Search"]').click(function() {
    $.cookie('clicked', 'true', {expires: 1}); // expires in 1 day
});

Тоді при завантаженні сторінки ви можете прочитати файл cookie так:

var clicked = $.cookie('clicked');

Оскільки у вашому випадку файли cookie зберігаються протягом сеансів, вам потрібно буде їх зняти, як тільки ви зробите все, що з цим потрібно. Ви не хотіли б, щоб користувач повернувся через день і все ще clickedвстановив значення true.

if(clicked === "true") {
    //doYourStuff();
    $.cookie('clicked', null);
}

(не-jQuery спосіб встановити / прочитати файли cookie можна знайти тут )

Я особисто не використовував би cookie для чогось такого простого, як запам'ятовування клацаного стану, але якщо рядок запиту не є опцією, і вам потрібно підтримувати справді старі браузери, які не підтримують sessionStorage, це буде працювати. Вам слід спочатку здійснити це за допомогою перевірки sessionStorage, і лише якщо це не вдається, використовуйте метод cookie.


window.name

Хоча це здається мені зламаною, яка, ймовірно, виникла ще до localStorage / sessionStorage, ви можете зберігати інформацію у window.nameвластивості:

window.name = "my value"

Він може зберігати лише рядки, тому, якщо ви хочете зберегти об’єкт, вам доведеться його обстежити, як у наведеному вище localStorageприкладі:

window.name = JSON.stringify({ clicked: true });

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

Це означає, що ви можете зберегти деяку інформацію на своїй сторінці, і поки користувач залишається на цій вкладці, ви можете отримати доступ до тієї самої інформації, навіть якщо він переглядав інший веб-сайт і назад. Загалом, я б радив не використовувати це, якщо вам не потрібно фактично зберігати міждоменну інформацію під час одного сеансу перегляду.


9
Тьфу, лише після написання я прочитав ваш опис щедрості, в якому говорилося "ні файлів cookie, ні локального сховища". Я залишатиму цей коментар незмінним для інших, кому він може знадобитися, але вам просто потрібно використовувати рядок запиту, я думаю.
Стефан Мюллер,

1
В основному я вже використовую localStorage у багатьох випадках для свого веб-додатку, і я хотів би уникати використання занадто багатьох змінних localStorage. Однак мені подобається ідея видалення елемента localStorage, коли я закінчу з ним. Це було те, про що я не думав, використовуючи мою змінну localStorage.
Неофіл

3
У разі запиту на пост ви можете змінити дію -attribute $ ("# formid"). Attr ("action", url + "& clicked = 1"), а також виявити GET або POST з $ ("# formid"). Attr ( "метод"), але це може не вирішити спосіб виявлення проблеми перезавантаження
Теро Толонен

2
@TheNewbie минув деякий час з моменту написання цієї відповіді, але я щойно додав нову опцію ( window.name). Він може просто робити саме те, що вам потрібно, не використовуючи файли cookie / localStorage.
Стефан Мюллер,

1
Я хотів додати, що локальне та сесійне сховище також не є повністю надійними в нових браузерах. Зазвичай є запасний варіант до window.name.
JavaScript

5

Спробуйте використати $.holdReady(),history

function show() {
  return $("form input[type=hidden]")
          .replaceWith(function(i, el) {
            return "<input type=text>"
          });
}

$.holdReady(true);
    if (history.state !== null && history.state.clicked === true) {
       // show hidden fields
       // if `history.state.clicked === true` ,
       // replace `input type=hidden` with `input type=text`
       show();
       console.log(history);

    } else {
        // don't show hidden fields
        console.log(history);
    }
$.holdReady(false);

  $(document).ready(function() {

    $("input[type=submit][value=Search]")
    .on("click", function(e) {
        e.preventDefault();
        if (history.state === null) {
          // do stuff
          history.pushState({"clicked":true});
          // replace `input type=hidden` with `input type=text`
          show();
          console.log(history);
        } else {
          // do other stuff
        };
    });

  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="POST">
    <input type="text" name="name" value="" />
    <input type="submit" value="Search" />
    <input type="hidden" />
    <input type="hidden" />
</form>


1

Використання localeStorageабо, sessionStorageздається, найкращий вибір.

Замість збереження clickedзмінної в області глобулу зберігайте її таким чином:

if(localeStorage.getItem("clicked") === null)
    localeStorage.setItem("clicked", "FALSE"); // for the first time

$(document).ready(function() {

    $("input[type='submit'][value='Search']").attr("onclick", "form.act.value='detailSearch';return true;");

    var clicked = localeStorage.getItem("clicked") == "FALSE" ? "TRUE" : "FALSE";

    localeStorage.setItem("clicked", clicked);

    if (clicked == "TRUE") {
      // show hidden fields
    } else {
      // don't show hidden fields
    }

});

Я маю намір не використовувати localstorage або sessionStorage бажано.
Неофіл

-5

Ви можете спробувати це:

 $("input[type='submit'][value='Search']").click(function(){
     form.act.value='detailSearch'; 
     clicked = true;  
     return true;
});

Коли сторінка перезавантажується, все одно отримують натиснуте значення як false.
Неофіл

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