Javascript 从缓存加载网页时不执行

Javascript Not Executing When Web Page Loaded from Cache

请参阅更新 3 了解最新状态。 我的 dojo 脚本出现错误 "Tried to register widget with id==contact-form but that id is already registered"。这个问题以前在这里出现过。我相信我的情况可能会有所不同。当我从网站上的一个页面转到另一个页面时出现错误。所有页面都有相同的脚本。如果我重新加载页面,我不会收到错误消息。如果我转到另一个网站然后返回,我不会收到错误。我的站点曾经使用 Symfony 框架。我刚刚在 Rails 上将其转换为 Ruby。我很确定我在使用 Symfony 时没有这个问题,但我并不肯定。我今天早上刚刚将我的名称服务器更改为新版本,所以我无法验证。该站点是 amcolan.info。如果您遵循 link,它应该可以在第一页上正常工作。将鼠标悬停在图像上进行测试。它应该放大。

这是实例化小部件的脚本:

require(["dojo/dom",
        "dojo/request",
        "dojo/dom-form",
        "dijit/Dialog",
        "dijit/form/Form",
        "dijit/form/TextBox",
        "dijit/form/ValidationTextBox",
        "dijit/form/Textarea",
        "dijit/form/Button",
        "dojox/validate/web",
        "dojo/domReady!"],
      function(dom, request, domForm, Dialog, Form, TextBox, ValidationTextBox, TextArea, Button ){

        alertDialog = new Dialog({
          title: "Email Result",
          content: "<p>No Content</p>",
          sytle: "width: 50em"
        });

        emailDialog = new Dialog({
          title: "Email Form",
          content: dom.byId("emailFormHTML").textContent,
          style: "width: 50em"
        });

        emForm = new Form({
        },"contact-form");

        toText = new TextBox({
          name: "addressee",
          readOnly: "readOnly",
          value: "Staff"
        },"to");

        nameText = new ValidationTextBox({
          name: "name",
          placeholder: "Your Name",
          required: "true",
          missingMessage: "We'd like to know who you are."
        },"name");

        emailText = new ValidationTextBox({
          name: "email",
          placeholder: "Your email",
          validator: dojox.validate.isEmailAddress,
          invalidMessage: "This is not a valid email address!"
        },"email");

        messageText = new TextArea({
          name: "message",
          placeholder: "Your message"
        },"message");

        sendBtn = new Button({
          label: "Send",
          onClick: function(){
            if (emForm.validate() == true){
              // Post the data to the server
              request.post("<%= contact_create_path %>",
                      {data: domForm.toObject("contact-form"),
                        // Wait 2 seconds for a response
                        timeout: 4000

                      }).then(function(response){
                        emailDialog.hide();
                        alertDialog.set("content", response)
                        alertDialog.show();
                      });
            }
          }
        },"submit-btn");
      });
</script>

如果我注释掉联系表单小部件,它会在下一个小部件上出错。这可能与 Rails 处理页面的方式有关吗?

更新

在创建小部件之前,我可以通过测试小部件来解决问题:

        emform = registry.byId("contact-form");
        if (!emform){
          emForm = new Form({
          },"contact-form");}

对所有小部件执行此操作后,该错误就消失了。该修复程序可能导致其他人。我仍然想知道为什么我有这个问题。我是否错过了一些关于保留小部件的基本 Javascript 或 dojo 概念?

更新 2

我以为我成功了,但没有。我不再收到任何错误。从站点上的另一个页面导航时,我仍然遇到 Javascript 未执行的问题。同样,如果我重新加载页面或从另一个网站输入,它工作正常。这是启用页面底部联系人 link 的 Javascript:

require(["dojo/on",
    "dojo/dom",
    "dojo/mouse",
    "dojo/dom-style",
    "dojo/domReady!"],
function(on, dom, mouse, style)
{
    var emailLink = dom.byId("emailClickable");

    on(emailLink, "click", function(evt){
        toText.set("value","Site Administrator");
        emailDialog.show();
    });
    on(emailLink, mouse.enter, function(evt){
        style.set(emailLink, "cursor", "pointer")
    });
});

更新 3

我在所有 javascript 函数中加入了 console.info 语句。当我在站点内逐页浏览时,我没有看到任何消息。我还在 Firebug 网络选项卡中注意到该问题仅在从缓存加载页面时出现。

您的小部件需要其他小部件才能完全启动和初始化(联系表格)。在这种情况下,您应该启动您的小部件,直到所有其他 dojo 小部件完成加载并初始化页面上的所有小部件。

因此将 "dojo/domReady!" 替换为 "dojo/ready" 并将其全部包装在 ready 函数中。有关详细信息,请查看 dojo guide on dojo/ready here.

不,不是外国政府试图破坏我的代码的稳定性,而是 turbolinks,或者至少是我对它的使用。在我的 header 中,我有:

<%#= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application' %>

我通过注释掉 turbolinks include 并添加一个没有它的 include 来解决这个问题。我还在应用程序文件中注释掉了 turbolinks require 语句。这里是关于 Turbolinks 如何工作的描述来自 their site:

Turbolinks makes following links in your web application faster. Instead of letting the browser recompile the JavaScript and CSS between each page change, it keeps the current page instance alive and replaces only the body and the title in the head. Think CGI vs persistent process.

我的猜测是 turbolinks 并没有通过保持页面实例活动来节省一切。这可能与我使用 dojo 的事实有关。他们对 jQuery 的 fix/workaround 的描述似乎证实了这一点:

If you have a lot of existing JavaScript that binds elements on jQuery.ready(), you can pull the jquery.turbolinks library into your project that will trigger ready() when Turbolinks triggers the page:load event. It may restore functionality of some libraries.

Add the gem to your project, then add the following line to your JavaScript manifest file, after jquery.js but before turbolinks.js: