【问题标题】:Preventing Links before jQuery is Loaded在加载 jQuery 之前阻止链接
【发布时间】:2010-09-28 09:45:24
【问题描述】:


如何在加载 jQuery 之前阻止点击事件的链接?
原因是我很少有通过 jQuery ajax 函数进行 AJAX 调用的链接,如果用户在加载 jQuery 框架之前单击它们,浏览器将无法触发 jQuery ajax 函数,并且将遵循链接 href="..." 谢谢。

编辑:我可以用这个吗?

<head>
...
  <script type="text/javascript">
   window.onload = prevCl();
   function prevCl() {
    var links = document.links[];
    links.onclick = check();
   }
   function check() {
    if (typeof jQuery == 'undefined') { 
     return false;
    }
   }
  </script>
</head>

【问题讨论】:

  • 您可以尝试一种 UI 方法。也许创建一个预加载器。
  • 我已经用一个例子更新了 Sean Hogan 的答案。他对如何处理这件事是绝对正确的。

标签: javascript jquery ajax javascript-events onclick


【解决方案1】:

四种选择:

选项 0

去阅读Sean Hogan's answer,他指出这可以通过委托来完成(doh!),我整理了一个示例实现。

选项 1

您可以将链接的href 设为“#”,直到加载 jQuery,然后(如果合适)将其更改为真正应该的样子。您可以将 href 的内容存储在 data- 属性中,例如:

<a href='javascript:;' data-href='realtarget.html'>blah</a>

然后:

jQuery(function($) {
    $("a[data-href]").each(function() {
        var $this = $(this);
        $this.attr("href", $this.attr("data-href"));
    });
});

同样,只有当您确实需要将 href 设置为 href 时,最后一点。如果您通过 JavaScript 处理点击,则无需。

如果验证是您开发周期的重要组成部分,请务必注意data-xyz 形式的属性在 HTML4 及之前的版本中无效(浏览器实际上并不关心,但同样,如果您使用验证... )。它们从 HTML5 开始生效。

选项 2

使用内联 onclick 属性在 jQuery 加载之前拦截点击并基本上说“对不起,等一下”。因此,在文件顶部script标签中:

function sorryLoading() {
    alert("Sorry, the page is still loading, one moment please.");
    return false;
}

...然后在链接上:

<a href='realtarget.html' class='sorry' onclick='return sorryLoading();'>blah</a>

...然后在 jQuery 加载时删除 onclick

jQuery(function($) {
    $("a.sorry").removeClass('sorry').attr("onclick", "").click(yourRealClickHandler);
});

(如果它们没有相同的点击处理程序,您可以保留最后一点 - click 调用 - 关闭。)

我使用上面的一个类来区分这些链接和其他可能具有内联 onclick 的链接(否则,令人惊讶的是,选择器“a[onclick]”实际上适用于 Linux 和 IE6 的 Chrome、Opera 和 Firefox和 IE8 在 Windows 上)。

选项 3

因为听起来您希望页面在 jQuery 加载之前无法正常工作,所以这里有另一种方法:

  1. 确保 jQuery 的脚本标记位于页面的 head 部分(而不是底部,我通常建议将其放置在底部)。
  2. 在页面的最底部,就在关闭 body 标记之前,连接您的点击处理程序而不将它们包装在 jQuery.ready 调用(或其任何快捷方式)中。

原因是这样的:#1 将确保 jQuery 本身在页面被渲染之前被加载,而#2 将连接处理程序尽快。 Google 建议在页面末尾使用类似的标签(而不是 ready 函数或类似函数),并表示到那时,DOM 元素就可以被发现了。


另外,当然,您希望通过执行所有页面加载优化工作来确保链接不执行用户期望的时间尽可能短你可以。点击一个链接却没有让它看起来像它所做的那样做会导致糟糕的用户体验。

【讨论】:

  • 谢谢,但它是一个巨大的 DOM 操作,并且在 SEO 和页面加载速度方面存在自己的问题。 :)
  • @Ali:关于 SEO 的要点。正如你所指出的,我正在添加另一个选项。
  • 感谢 T.J. 但我有一些链接,我认为 javascript 可以做到但我不擅长没有框架的 javascript 我试图编写一个函数但没有工作。 (你能在我的问题中查看这个函数吗?我编辑了)
  • @Ali:不,您不能为此使用window.onloadwindow.onload 在加载过程中非常非常晚发生(例如,在 jQuery.ready 之后)。我添加了选项 3,但我想说选项 2 可能是您最好的选择。
  • 选项 1 对我很有效。但是,我没有使用仍然将人们引导回顶级页面的#,而是使用了 javascript:void,因此当您单击时没有任何反应。谢谢人!这真的很有帮助。
【解决方案2】:

您可以使用事件委托:jQuery live()delegate() 方法的 DOM 等效项。

以下方法可能有效:

<head>

<script>
function linkMatcher(node) { // modify this if not all links are disabled
 if (node.href) return true;
 else return false;
}

document.onclick = function(e) {
 e = e || window.event;
 var target = e.target || e.srcElement;
 for (var node=target; node!=document; node=node.parentNode) {
  if (node.tagName == "A") return !linkMatcher(node);
 }
}
</script>
</head>

编辑:这将永久禁用链接。可以通过删除事件处理程序重新启用它们,例如document.onclick = null


下面的complete, live example 适用于 Linux 的 Chrome、Opera 和 Firefox,以及适用于 Windows 的 IE6 和 IE8。它可以防止点击“等待”类的链接(如果你喜欢,你可以做所有的链接)并记住第一个点击的链接。然后它模拟长时间的加载延迟(五秒),然后在链接上挂接 jQuery 处理程序并删除阻止点击的文档级处理程序,然后在被点击的链接上触发 jQuery 处理程序(请注意,这只触发处理程序,而不是底层的默认行为——但是当你想触发你的 ajax 东西时,我认为这没关系)。 — T.J.克劳德

HTML:

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<meta charset=utf-8 />
<title>Link Click Delay Test Page</title>
<!--[if IE]>
  <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
  article, aside, figure, footer, header, hgroup, 
  menu, nav, section { display: block; }
  body {
    font-family: sans-serif;
  }
  p {
    margin: 0px;
  }
</style>
<script type='text/javascript'>
  // A scoping function to avoid creating global symbols
  (function() {
    // Figure out what to hook clicks on
    var container =
        document.body ||
        document.documentElement ||
        document;

    // Hook clicks that reach the bottom level
    hookClicks();
    function hookClicks() {
      if (container.attachEvent) {
        container.attachEvent("onclick", handleClick);
      }
      else if (document.addEventListener) {
        container.addEventListener("click", handleClick, false);
      }
    }

    // Set up an unhook function for jQuery to call
    window.unhookClicks = unhookClicks;
    function unhookClicks() {
      if (container.attachEvent) {
        container.detachEvent("onclick", handleClick);
      }
      else if (document.addEventListener) {
        container.removeEventListener("click", handleClick, false);
      }
    }

    // Handle clicks
    function handleClick(event) {
      var target;

      // Handle Microsoft vs. W3C event passing style
      event = event || window.event;

      // Get the target (again handling Microsoft vs. W3C style)
      target = event.target || event.srcElement;

      // Do we have a target that's an A with the class "wait"?
      if (target &&
          target.tagName.toUpperCase() === "A" &&
          (" " + target.className + " ").indexOf(" wait ") >= 0
         ) {
        // It's a link we want to prevent for the moment
        // Remember the element that was clicked if there
        // isn't already one (or replace it, depends on the
        // UX you want to provide
        if (!window.pendingLink) {
          window.pendingLink = target;
        }

        // Prevent it from being processed
        if (event.preventDefault) { // If W3C method...
          event.preventDefault();
        }

        // This should work if preventDefault doesn't
        return false;
      }
    }
  })();
</script>
</head>
<body>
  <p><a href='http://www.google.com' class='wait'>Google</a>
    - This one waits
  <br><a href='http://news.bbc.co.uk' class='wait'>BBC News</a>
    - This one also waits
  <br><a href='http://www.cnn.com'>CNN</a>
    - This one doesn't wait, it goes immediately
    </p>
</body>
</html>​

JavaScript(无论您的 jQuery ready 处理程序在哪里):

jQuery(function($) {

  // Use setTimeout to fake a long delay loading
  setTimeout(function() {

    // Hook up our proper click handling
    // Obviously, replace this with whatever does the ajax
    $("a.wait").click(function(event) {
      alert("The jQuery handler for " + this.href + " link was triggered.");
    });

    // If we have clicks disabled, enable them
    if (window.unhookClicks) {
      window.unhookClicks();
      window.unhookClicks = undefined;
    }

    // Do we have a pending link to follow?
    if (window.pendingLink) {
      // Yes, grab it and clear it
      var $link = $(window.pendingLink);
      window.pendingLink = undefined;

      // Trigger any jQuery event handlers on it.
      // Note that this will NOT follow the link,
      // just trigger jQuery event handlers that
      // are on the link.
      $link.click();
    }

    // We've loaded!
    $("<p>Finally loaded!</p>").appendTo(document.body);

    // End of fake delay function
  }, 5000);

});​

【讨论】:

  • Doh! 当然,在呈现页面时捕获文档级别的点击是实现此目的的方法。我冒昧地添加了一个完整的实时示例(并使用attachEvent / addEventListener 而不是onclick)。
【解决方案3】:

我没试过,但是理论上只要jquery未完成就给所有a元素添加一个不带jquery的事件处理程序就可以阻止默认动作(打开链接)?

getElementsByTagNames('a').addEventListener('click',function (event) {
  if (typeof jQuery == 'undefined') { 
    event.preventDeafault();
  }
},false)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多