Rails5/jQuery中click touchstart事件仅首次加载有效问题求助
问题:Turbolinks导致Bourbon/Refills滑动面板点击事件失效
我在用Bourbon/Refills的sliding_panel组件做导航菜单,给相关元素绑定了on('click touchstart')事件,用toggleClass控制菜单显示隐藏。页面第一次加载时没问题,但后续切换页面后事件就失效了。我怀疑是Turbolinks的问题,装了jquery-turbolinks gem配置好还是没解决,有人遇到过类似情况吗?
我的代码如下:
模板代码 (_navbar.html.erb)
<button type="button" class="js-menu-trigger sliding-panel-button"> Click for Sliding Panel </button> <nav class="js-menu sliding-panel-content"> <ul> <li><%= link_to 'Users', users_path %></li> <li><a href="javascript:void(0)">Item 2</a></li> <li><a href="javascript:void(0)">Item 3</a></li> </ul> </nav> <div class="js-menu-screen sliding-panel-fade-screen"></div>
JavaScript代码 (sliding_panel.js)
$(document).ready(function(){ $('.sliding-panel-button,.sliding-panel-fade-screen,.sliding-panel-close').on('click touchstart',function (e) { $('.sliding-panel-content,.sliding-panel-fade-screen').toggleClass('is-visible'); e.preventDefault(); }); });
SCSS代码 (sliding_panel.scss)
.sliding-panel-content { $action-color: #477DCA !default; $dark-gray: #333 !default; $sliding-panel-border-color: $dark-gray; $sliding-panel-background: lighten($sliding-panel-border-color, 5%); $sliding-panel-color: #fff; $sliding-panel-border: 1px solid $sliding-panel-border-color; $sliding-panel-background-hover: $action-color; $sliding-panel-color-hover: #fff; $sliding-panel-background-focus: lighten($sliding-panel-background, 5%); @include position(fixed, 0 auto 0 0); @include size(220px, 100%); background: $sliding-panel-background; -webkit-overflow-scrolling: touch; overflow-y: auto; transform: translateX(-220px); transition: all 0.25s linear; z-index: 999999; ul { padding: 0; margin: 0; } li { list-style: none; } li a { border-bottom: $sliding-panel-border; color: $sliding-panel-color; display: block; font-weight: bold; padding: 1em; text-decoration: none; &:focus { background-color: $sliding-panel-background-focus; } &:hover { background-color: $sliding-panel-background-hover; color: $sliding-panel-color-hover; } } &.is-visible { transform: translateX(0); } } .sliding-panel-fade-screen { @include position(fixed, 0); background: black; opacity: 0; transition: all 0.2s ease-in-out; visibility: hidden; z-index: 999998; &.is-visible { opacity: 0.4; visibility: visible; } } .sliding-panel-button { cursor: pointer; display: inline-block; outline: none; padding: 10px 16px; position: relative; img { height: 1.3em; } }
解答
嘿,我之前也碰到过一模一样的问题!Turbolinks的坑就在这儿——它会替换页面的内容,但不会重新执行$(document).ready()里的代码,所以新加载的页面里的元素根本没绑定上事件。jquery-turbolinks有时候能解决,但不是所有情况都管用,尤其是当代码结构没适配Turbolinks的时候。给你两个靠谱的解决办法:
方法一:用Turbolinks的turbo:load事件替代$(document).ready()
Turbolinks会在页面加载完成(包括首次加载和Turbolinks跳转后的加载)时触发turbo:load事件(如果是Turbolinks 5之前的版本是turbolinks:load,注意区分版本)。把你的代码改成这样:
$(document).on('turbo:load', function(){ // 先解绑再绑定,避免重复绑定导致多次触发 $('.sliding-panel-button,.sliding-panel-fade-screen,.sliding-panel-close') .off('click touchstart') .on('click touchstart',function (e) { $('.sliding-panel-content,.sliding-panel-fade-screen').toggleClass('is-visible'); e.preventDefault(); }); });
方法二:用事件委托(Event Delegation)
另一个更稳妥的办法是把事件绑定在document这类一直存在的元素上,不管元素是一开始就存在还是后来动态加载的,事件都能通过冒泡触发:
$(document).on('click touchstart', '.sliding-panel-button,.sliding-panel-fade-screen,.sliding-panel-close', function (e) { $('.sliding-panel-content,.sliding-panel-fade-screen').toggleClass('is-visible'); e.preventDefault(); });
这种方式不需要依赖Turbolinks的特定事件,兼容性更好,就算以后Turbolinks版本更新也不容易出问题,我个人更推荐这个方法!
你可以先试试方法二,应该能直接解决问题!
内容的提问来源于stack exchange,提问作者BB123
相关产品推荐
相关产品推荐

