페이지로드 사이에 변수 유지


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 변수는 모두 깨끗합니다. 전체 범위가 재활용됩니다.
Dave Alperovich 2015

대부분의 페이지를 "일부"에 넣고 새로 고치지 않는 이유는 무엇입니까?
Dave Alperovich

부분이란 무엇입니까? 모르게 죄송합니다.
Neophile

ajax를 통해 양식을 제출하고 제출 후 필드를 표시하는 것을 고려 했습니까?
dannyshaw 2015 년

1
페이지를 새로 고침해야하는 이유에 대해 자세히 설명해 주 시겠습니까? 우리가 그것을 피할 수 있다면 , 당신이 사용 하는 대신 이벤트 preventDefault에서 원하는 것을 할 수 있습니다 .submitclick
Peleg

답변:


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>

페이지를 처음로드 할 때 쿼리 문자열이 설정되지 않습니다. 이 양식을 제출 하면 입력 의 namevalue조합이 쿼리 문자열에 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를 사용하고 있다면 문제가 될 수 있습니다.

또한 더 큰 데이터 세트의 경우 이는 최적이 아닙니다. 문자열을 전달하는 것은 큰 문제는 아니지만 데이터의 배열과 개체의 경우 웹 저장소 또는 쿠키를 사용해야합니다. 세부 정보는 브라우저마다 약간 씩 다르지만 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'));

브라우저 지원은 매우 훌륭 하므로 정말 오래되고 모호한 브라우저를 지원할 필요가없는 한 안전하게 사용할 수 있습니다. 웹 스토리지는 미래입니다.


쿠키

웹 스토리지의 대안은 쿠키에 데이터를 저장하는 것입니다. 쿠키는 주로 서버 측 데이터를 읽기 위해 만들어 지지만 순수하게 클라이언트 측 데이터에도 사용할 수 있습니다.

이미 jQuery를 사용하고 있으므로 쿠키 설정이 매우 쉽습니다. 여기서도 click이벤트를 사용 하지만 어디에서나 사용할 수 있습니다.

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

그런 다음 페이지로드시 다음과 같이 쿠키를 읽을 수 있습니다.

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

귀하의 경우 세션에서 쿠키가 지속되므로 필요한 작업을 수행하는 즉시 쿠키 설정을 해제해야합니다. 사용자가 하루 후에 다시 돌아와서 여전히 clickedtrue로 설정하는 것을 원하지 않을 것 입니다.

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

(쿠키를 설정 / 읽는 비 jQuery 방법은 여기 에서 찾을 수 있습니다 )

개인적으로 클릭 한 상태를 기억하는 것과 같은 간단한 작업에는 쿠키를 사용하지 않지만 쿼리 문자열이 옵션이 아니고 sessionStorage를 지원하지 않는 정말 오래된 브라우저를 지원해야하는 경우 작동합니다. 먼저 sessionStorage를 확인하여이를 구현해야하며 실패한 경우에만 쿠키 메서드를 사용하십시오.


window.name

이것은 아마도 localStorage / sessionStorage 이전에 시작된 해킹처럼 보이지만 window.name속성에 정보를 저장할 수 있습니다 .

window.name = "my value"

문자열 만 저장할 수 있으므로 객체를 저장하려면 위의 localStorage예 와 같이 문자열 화해야합니다 .

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

가장 큰 차이점은이 정보는 페이지 새로 고침뿐만 아니라 다른 도메인에서도 유지된다는 것입니다. 그러나 현재있는 탭으로 제한됩니다.

즉, 페이지에 일부 정보를 저장할 수 있으며 사용자가 해당 탭에 머무르는 한 다른 웹 사이트를 검색했다가 돌아 오더라도 동일한 정보에 액세스 할 수 있습니다. 일반적으로 단일 브라우징 세션 동안 교차 도메인 정보를 실제로 저장해야하는 경우가 아니라면 이것을 사용하지 않는 것이 좋습니다.


9
글을 쓴 후에야 "쿠키 나 로컬 저장소 없음"이라는 현상금 설명을 읽었습니다. 이 주석이 필요할 수있는 다른 사용자를 위해 그대로 유지 하겠지만, 제가 추측하는 쿼리 문자열을 사용해야합니다.
Stephan Muller

1
기본적으로 저는 이미 웹 응용 프로그램에 대해 많은 경우에 localStorage를 사용하고 있으며 너무 많은 localStorage 변수를 사용하지 않으려 고합니다. 그러나 일단 작업이 끝나면 localStorage 항목을 제거하는 것이 좋습니다. 그것은 내 localStorage 변수를 사용할 때 생각하지 못한 것입니다.
Neophile

3
게시 요청의 경우 -attribute $ ( "# formid"). attr ( "action", url + "& clicked = 1") 작업을 수정하고 $ ( "# formid"). attr (에서 GET 또는 POST를 감지 할 수도 있습니다. "방법")하지만 다시로드 문제를 감지하는 방법을 해결하지 않을 수 있습니다
테로 Tolonen

2
@TheNewbie이 답변을 작성한 지 오래되었지만 새 옵션 ( window.name)을 추가했습니다 . 쿠키 / localStorage를 사용하지 않고 필요한 작업을 정확히 수행 할 수 있습니다.
Stephan Muller

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하는 것이 가장 좋은 방법 인 것 같습니다.

구원의 Intead clickedGLOBLE 범위 매장이 이런 식으로 변수를 :

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를 사용하지 않을 계획입니다.
Neophile

-5

이것을 시도해 볼 수 있습니다.

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

페이지가 다시로드 될 때 여전히 클릭 된 값을 false로 가져옵니다.
Neophile

1
@TheNewbie 쿼리 문자열을 전달할 수 있다고 생각하십니까? 페이지 새로 고침을 사용하면 현재 접근 방식이 작동하지 않습니다.
renakre
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.