Сохранять переменные между загрузками страницы

97

Я пытаюсь зафиксировать нажатие кнопки отправки моей формы, и если форма отправлена, страница обновляется, и я показываю несколько скрытых полей. Я хотел бы зафиксировать, была ли форма отправлена ​​раньше или нет, и если она была отправлена ​​при перезагрузке, я хотел бы показать скрытые поля. Я пытался использовать глобальную переменную для достижения этой цели, однако мне не удалось заставить ее работать должным образом.

Вот что я пробовал:

  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, что используете)
Пелег,

Ответы:

207

Поскольку 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который сохраняет данные только во время вашего текущего сеанса просмотра. Последнее полезно для вас здесь, потому что вы не хотите, чтобы для параметра clicked было установлено значение 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);
}

(способ установки / чтения файлов cookie, отличный от jQuery, можно найти прямо здесь )

Лично я бы не стал использовать 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.
Neophile
3
В случае почтового запроса вы можете изменить атрибут action -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>

гость271314
источник
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
    }

});
me_digvijay
источник
Я намерен не использовать localstorage или sessionStorage предпочтительно.
Neophile
-5

Вы можете попробовать это:

 $("input[type='submit'][value='Search']").click(function(){
     form.act.value='detailSearch'; 
     clicked = true;  
     return true;
});
Renakre
источник
Когда страница перезагружается, они по-прежнему получают значение clicked как false.
Неофил
1
@TheNewbie, как вы думаете, можно передать строку запроса? с обновлением страницы текущий подход не будет работать.
Renakre