在页面加载之间保留变量

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

这是我尝试过的:

  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

由于HTTP是无状态的,每次加载页面时,它都会使用您在JavaScript中设置的任何内容的初始值。您无法在 JS 中设置全局变量,而只是在再次加载页面后使该值保持不变。

有几种方法可以将值存储在另一个位置,以便可以使用JavaScript在加载时对其进行初始化


查询字符串

使用该方法提交表单时,url 将使用查询字符串 () 进行更新。您可以通过将表单中的输入字段设置为特定值来利用这一点。这是最简单的示例:GET?parameter=value&something=42

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

在初始加载页面时,不设置查询字符串。提交此表单时,输入的 和 组合将作为 在查询字符串中传递。因此,当页面再次加载该查询字符串时,您可以检查是否单击了该按钮。namevalueclicked=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,那么这可能会有问题。

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


网络存储

随着HTML5的引入,我们还获得了Web Storage,它允许您在页面加载期间在浏览器中保存信息。有一个可以保存数据更长的时间(只要用户不手动清除它),并且仅在当前浏览会话期间保存数据。后者在这里对您很有用,因为您不希望在用户稍后返回时将“单击”设置为 true。localStoragesessionStorage

在这里,我在按钮单击事件上设置了存储,但您也可以将其绑定到表单提交或其他任何内容。

$('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 在您的案例中跨会话持续存在,因此您需要在完成任何需要对其进行操作后立即取消设置它们。您不希望用户在一天后返回,并且仍设置为 true。clicked

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

(设置/读取 cookie 的非 jQuery 方法可以在这里找到)

我个人不会将cookie用于记住单击状态的简单事情,但是如果查询字符串不是一个选项,并且您需要支持不支持会话存储的真正旧的浏览器,这将起作用。您应该首先通过检查会话存储来实现它,并且仅当失败时才使用cookie方法。


window.name

尽管这对我来说似乎是一个可能起源于localStorage/sessionStorage之前的黑客攻击,但您可以将信息存储在属性中:window.name

window.name = "my value"

它只能存储字符串,因此,如果要保存对象,则必须将其字符串化,就像上面的示例一样:localStorage

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

主要区别在于,此信息不仅保留在页面刷新中,而且还保留在不同的域中。但是,它仅限于您所在的当前选项卡。

这意味着您可以在页面上保存一些信息,只要用户留在该选项卡中,即使他浏览到另一个网站并返回,您也可以访问相同的信息。一般来说,我建议不要使用它,除非你需要在单个浏览会话期间实际存储跨域信息。


答案 2

尝试使用 $.holdReady()历史记录

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>