在页面加载之间保持变量


95

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

这是我尝试过的:

  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

您为什么不将页面的大部分放入“部分”并刷新呢?
Dave Alperovich,2015年

什么是局部的?抱歉,我不知道。
Neophile

您是否考虑过通过ajax提交表单并在提交后显示字段?
dannyshaw,2015年

1
您能否详细说明为什么需要刷新页面?如果我们能避免它,你可能能够做到你想,如果你正是preventDefaultsubmit事件(而不是click你使用。)
法勒

Answers:


202

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

您可以通过两种方法将值存储在其他位置,以便可以在加载时使用JavaScript对其进行初始化


请求参数

使用GET方法提交表单时,网址会使用查询字符串(?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,则可能会出现问题。

另外,对于较大的数据集,这不是最佳的。传递字符串并不重要,但是对于数据的数组和对象,您可能应该使用Web存储或cookie。尽管各浏览器的细节有所不同,但URI长度的实际限制约为2000个字符


网络存储

随着HTML5的引入,我们还获得了Web存储,它使您可以跨页面加载在浏览器中保存信息。有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'));

浏览器支持非常好,因此除非您需要支持真正的旧/模糊浏览器,否则应该放心使用。网络存储是未来。


饼干

Web存储的替代方法是将数据保存在cookie中。Cookies主要用于读取服务器端的数据,但也可以用于纯客户端数据。

您已经使用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
gh,直到写完之后,我才读到您的赏金描述,上面写着“没有cookie或本地存储”。对于可能需要使用此注释的其他人,我将保留此注释不变,但是您只需要使用我猜想的查询字符串即可。
斯蒂芬·穆勒

1
基本上,我已经在很多情况下为我的Web应用程序使用了localStorage,并且我想避免使用太多的localStorage变量。但是,我确实喜欢在完成后删除localStorage项的想法。那是我使用localStorage变量时没有想到的。
Neophile

3
在发布请求的情况下,您可以修改操作-属性$(“#formid”)。attr(“ action”,url +“&clicked = 1”),还可以从$(“#formid”)。attr( “办法”),但它可能没有解决如何检测重装问题
泰罗Tolonen

2
@TheNewbie自从我写了这个答案已经有一段时间了,但是我只是添加了一个新选项(window.name)。它可能只是在不使用cookie / 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

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

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。
Neophile

-5

您可以尝试以下方法:

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

当页面重新加载时,仍然获得点击值为false。
Neophile

1
您认为@TheNewbie可以传递查询字符串吗?使用页面刷新,当前方法将行不通。
renakre'5
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.