在页面加载之间保留变量

时间:2015-05-01 12:13:53

标签: javascript jquery form-submit persistent-storage

我正在尝试捕获表单的提交按钮,如果表单已提交,页面将刷新并显示一些隐藏字段。我想捕获表单是否已经提交之前,如果它是在重新加载时提交的,我想取消隐藏隐藏的字段。我试图使用全局变量来实现这一点,但是我无法使其正常工作。

以下是我的尝试:

  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
    }
  });

有关此代码有什么问题的任何建议吗?

4 个答案:

答案 0 :(得分:157)

由于HTTP是无状态的,因此每次加载页面时,它都将使用您在JavaScript中设置的任何值的初始值。您无法在JS中设置全局变量,只需在重新加载页面后保持该值。

有几种方法可以将值存储在另一个地方,以便您可以使用JavaScript在加载时初始化它

查询字符串

使用GET方法提交表单时,会使用查询字符串(?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');

Source

使用此功能取决于您的表单当前的工作方式,如果您已使用POST,则可能会出现问题。

此外,对于较大的数据集,这不是最佳的。传递字符串并不是什么大问题,但对于数组和数据对象,您应该使用Web存储或cookie。虽然浏览器的细节略有不同,但URI长度的实际限制大约为2000 characters

网络存储

随着HTML5的推出,我们还获得了Web Storage,它允许您跨页面加载在浏览器中保存信息。 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'));

浏览器支持是pretty great,因此除非您需要支持真正古老/模糊的浏览器,否则您应该安全使用它。 Web存储是未来。

<强>缓存

Web Storage的替代方法是将数据保存在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方式right here

我个人不会使用cookie来记住单击状态这样简单的事情,但是如果查询字符串不是一个选项而你需要支持那些不支持sessionStorage的旧浏览器,那么这将起作用。您应首先检查sessionStorage,并且只有在失败时才使用cookie方法。

<强> window.name

虽然这对我来说似乎是一个hack,可能源于localStorage / sessionStorage之前,你可以将信息存储在window.name属性中:

window.name = "my value"

它只能存储字符串,所以如果你想保存一个对象,就必须像上面的localStorage例子那样对它进行字符串化:

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

主要区别在于,此信息不仅保留在页面刷新,还保留在不同的域中。但是,它仅限于您当前的标签。

这意味着您可以在页面上保存一些信息,只要用户留在该标签中,即使他浏览到其他网站并返回,您也可以访问相同的信息。一般情况下,除非您需要在单个浏览会话期间实际存储跨域信息,否则我建议不要使用此功能。

答案 1 :(得分:5)

尝试使用$.holdReady()history

<script src="jquery.js" type="text/javascript"></script>
</head>
<body>
<form method="POST">
    <input type="text" name="name" value="" />
    <input type="submit" value="Search" />
    <input type="hidden" />
    <input type="hidden" />
</form>
<script type="text/javascript">
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>
</body>

答案 2 :(得分:1)

使用localeStoragesessionStorage似乎是最好的选择。

在全局范围内保存clicked变量的Intead以这种方式存储:

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
    }

});

答案 3 :(得分:-3)

你可以试试这个:

var express = require('express'),
    app     = express(),
    port    = parseInt(process.env.PORT, 10) || 8080;

//you can remove the app.configure at all in case of it is not supported
//directly call the inner code     
app.configure(function(){
  app.use(bodyParser.urlencoded());
  //in case you are sending json objects 
  app.use(bodyParser.json());
  app.use(app.router);
});

app.listen(port);

app.post("/module", function(req, res) {
  res.send(req.body);
});