刷新页面后才能使JavaScript生效。

3
我正在使用Bootstrap 3.2.0。我尝试同时使用两个Bootstrap JavaScript特性:Scrollspy和Affix。目标是在侧边创建一个可以使用Affix滚动的Scrollspy。演示 以下是我的JavaScript文件,在Rails资产管道中由head引入。
$(document).ready(function () {

  // Use affix plugin
  $("#sidebar").affix({
    offset: { top: 280 }
  });

  // Use Scrollspy
  $('body').scrollspy({ target: '#sidebar', offset: 200 });

}

滚动监听功能运作正常,但固定插件不行,除非我在初始加载后刷新页面。在Chrome的开发者工具中,我注意到JavaScript第一次加载页面时没有将affix-top添加到sidebar
当我直接将固定插件JavaScript放入body中时,它可以在不刷新的情况下工作。但我真的不想使用内联JavaScript。而且我真的很好奇为什么会出现这种奇怪的行为。
我正在使用Rails 4.1.5。
2个回答

4

Turbolinks

问题几乎可以肯定是Turbolinks - 一种旨在通过仅检索新请求中的<body>标签而保留<head>的JavaScript库来加速页面加载。

虽然Turbolinks非常有效,但它往往会通过不刷新您页面上的JavaScript而“破坏”应用程序功能。

--

问题在于,因为JS仅绑定在当JS已被加载时加载的DOM元素上。如果Turbolinks加载新元素而不刷新JS,则会让JS错误地认为您没有刷新元素/页面,从而防止其能够“绑定”到您的新元素上。

解决方法有两个:

  1. JS 从一个一致的元素(通常为document)代理
  2. 使用Turbolinks "事件钩子"来管理页面上的JS事件

以下是我会做的:

#app/assets/javascripts/application.js
var loaded = function(){

  // Use affix plugin
  $("#sidebar").affix({
    offset: { top: 280 }
  });

  // Use Scrollspy
  $('body').scrollspy({ target: '#sidebar', offset: 200 });

}
$(document).on("page:load ready", loaded);

谢谢,我通过将整个代码包装在 $(document).ready(function() {})$(window).bind('page:change', function() {}) 中使其工作。但是你的解决方案更简单。 - mc9
我只是想理解这种情况。我对这个问题的理解是,在Turbolinks加载JS文件后,我添加了新的DOM元素,除非刷新页面,否则JS文件无法绑定到新元素。这正确吗? - mc9

3

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