如何在页面首次加载时执行 JavaScript 函数?

23

我想知道是否有一种方法可以仅在第一次页面加载时执行 JavaScript 函数,然后不在任何后续重新加载中执行该函数。

我能否找到一种解决方法?


4
这取决于你如何定义“第一次页面加载”,但通常情况下,这是通过cookie或localStorage来处理的。 - zzzzBov
5个回答

49
下面的代码将在onload事件触发后执行。该语句通过使用标志(hasCodeRunBefore),并将其存储在localStorage中,检查一次性函数是否已经被执行过,if没有被执行过。请注意保留{和}符号。
window.onload = function () {
    if (localStorage.getItem("hasCodeRunBefore") === null) {
        /** Your code here. **/
        localStorage.setItem("hasCodeRunBefore", true);
    }
}

注意:如果用户通过任何方式清除他们浏览器的localStorage,那么该函数将再次运行,因为标志(hasCodeRunBefore)将被删除。

好消息...

使用localStorage可能会很繁琐,因为需要操作符和冗长的函数名称。我创建了一个基本的模块, 以简化这个过程,所以上面的代码将被替换为:

window.onload = function () {
    if (!ls.exists('has_code_run_before')) {
        /** Your code here... **/
        ls.set.single('has_code_run_before', true);

        /** or... you can use a callback. **/
        ls.set.single('has_code_run_before', true, function () {
           /** Your code here... **/ 
        });
    }
};

更新 #1

根据@PatrickRoberts的评论,你可以使用in运算符来查看localStorage中是否存在一个变量键,因此

if (localStorage.getItem('hasCodeRunBefore') === null)

变成

if (!('hasCodeRunBefore' in localStorage))

并且更加简洁、清晰。其次,你可以像设置对象一样设置值(localStorage.hasCodeRunBefore = true),但它将被存储为字符串,而不是布尔值(或任何其他数据类型)。

1
关于“好消息”部分,规范确实允许使用Storage对象作为普通对象,但需要注意所有值都必须是字符串。例如,您可以通过'hasCodeRunBefore' in localStorage来检查是否存在,并通过localStorage.hasCodeRunBefore = true 来设置它。 - Patrick Roberts
@PatrickRoberts 啊,对了,没想到你可以用“in”来实现这个。谢谢你。 - Script47
@PatrickRoberts 感谢您的编辑,我本来想加上括号,但不确定是否需要。我在控制台中使用了一些虚拟数据进行测试,似乎没有括号也能正常工作(除非我做错了?)。出于好奇,您能否展示一个没有括号会失败的例子,或者这个括号是为了安全起见? - Script47
2
!'foo' in {} vs. !('foo' in {}) - Patrick Roberts

3
每次页面加载时,所有JavaScript代码都必须执行。如果脚本在页面上,则会执行。
在页面中包含的JavaScript代码中执行的逻辑可能会根据页面状态、提供的输入以及它接收到的任何其他信号(无论是来自服务器还是客户端)以不同的方式执行。
如果您正在使用服务器端语言,则可以选择有条件地呈现脚本,例如用户首次登录时。
如果您需要包含JavaScript而不考虑上下文,则需要侦听其他信号。
现代的简单解决方案是利用 localStoragelocalStorage 可用于为任何给定域存储自定义字符串值和自定义键值。
利用此功能的代码如下:
if (localStorage['...my key here...'] === '...my expected value here...') {
    // The page has been visited before
} else {
    // The page has not been visited before
    // OR
    // The user or script has cleared the localStorage value
}
localStorage['...my key here...'] = '...my expected value here...';

如果您只需要在客户端上运行事物,那么这一切都很好。有时候您可能需要让服务器知道页面是否被访问过。
(不太简单的)解决方案是使用document.cookie
if (/(?:^|;\s*)...my key here...=...my expected value here...(?:;|$)/.test(document.cookie)) {
    // the page has been visited before
} else {
    // The page has not been visited before
    // OR
    // The user or script has cleared the cookie
}
document.cookie = '...my key here...=...my expected value here...';

如果您需要推迟执行直到页面加载完成,那么只需在onload回调中包含脚本,可以通过将事件分配给窗口来实现:
window.onload = function () {
    // do stuff when the page has loaded
    //this will override any other scripts that may have been assigned to .onload
};

或者通过将事件处理程序绑定到窗口:
window.addEventListener('load', function () {
    // do stuff when the page has loaded
}, false);

2

这要看你对于“首次页面加载”是什么意思,因为这是主观的。

如果你想让函数在DOM解析后执行,但只有HTML而没有其他外部资源,请将其绑定到DOMContentLoaded事件。

document.addEventListener('DOMContentLoaded', fn);

否则,如果你想要等待外部资源加载完成后再触发事件,你应该将它绑定到 window 对象的 load 事件上,像这样:

window.addEventListener('load', fn);

这里有一些来自 Mozilla 开发者网络的链接,可以更详细地解释我刚才说的内容:

https://developer.mozilla.org/zh-CN/docs/Web/Events/load

https://developer.mozilla.org/zh-CN/docs/Web/Events/DOMContentLoaded

祝好运!


1
这似乎并没有回答问题,你只是提供了在页面加载或DOM加载时触发代码的方法,OP想要能够仅触发一次代码。 - Script47
这个答案正在Meta上讨论。 - Script47

2

function toBeExecutedOnFirstLoad(){
  // ...
}
if(localStorage.getItem('first') === null){
  toBeExecutedOnFirstLoad();
  localStorage.setItem('first','nope!');
}


1
我遇到了类似的问题,不同之处在于,我想在创建新实例时运行代码,需要执行某个特定的代码,然后在之后的重新加载中,该代码不应该被执行。 为此,类似于上面的localStorage解决方案,使用session storage代替:
fun_RunOnlyOnFirstPageLoad(){}
if(!$window.sessionStorage.getItem(hasRunBefore)){
   fun_RunOnlyOnFirstPageLoad();
   $window.sessionStorage.setItem(hasRunBefore, true);
}

使用 window.sessionStorage 仅在该会话期间存储值。这样,一旦选项卡关闭(会话结束,该值被清除),并且在每个新实例化上执行代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接