我想在带有Turbolinks的Rails应用程序中的表单上监视Submit事件。我提出了以下建议:
document.addEventListener('turbolinks:load', function(e) {
var arrangeForm;
arrangeForm = document.querySelector('#arrange-dust-form');
if (arrangeForm) {
return arrangeForm.addEventListener('submit', function(e) {
// do stuff on submit...
});
}
});
这可行,但是关于if (arrangeForm)
的部分似乎很尴尬。但是,如果我不检查表单是否存在,则导航到网站的其他页面时会收到错误消息,因为它试图将侦听器设置在不存在的元素上。
在不必检查每个turbolinks:load
事件中是否存在表单的情况下,是否有“正确”或“正式”的方式来执行此操作?我应该将事件附加到哪个更适用的节点上?
答案 0 :(得分:0)
对于仅在一页上运行且不包含在整个应用范围内的任何特定js的Rails方式,是在您感兴趣的视图页面上使用content_for:
<% content_for :myjava do %>
<script type='text/javascript'>
document.addEventListener('turbolinks:load', function(e) {
var arrangeForm;
arrangeForm = document.querySelector('#arrange-dust-form');
if (arrangeForm) {
return arrangeForm.addEventListener('submit', function(e) {
// do stuff on submit...
});
}
});
</script>
<% end %>
然后在您的layouts / application.html.erb文件中将其屈服于body标签的末尾,例如:
<body>
#whatever layout view code
<%= yield :myjava %>
</body>
答案 1 :(得分:0)
Turbolinks Readme建议使用事件委托来处理事件:
如果可能,请避免使用turbolinks:load事件将其他事件侦听器直接添加到页面正文上的元素。相反,请考虑使用事件委托在文档或窗口上一次注册事件侦听器。
例如:
window.addEventListener('submit', function (event) {
if (event.target.id === '#arrange-dust-form') {
// do stuff on submit…
}
})
这使我们的事件处理程序更加灵活,因为它不需要turbolinks:load
事件即可工作。如果您的#arrange-dust-form
是在turbolinks:load
之后动态添加的,或者即使您完全删除了Turbolink,该代码仍然可以使用。
上面的解决方案很好,但是每次要处理事件时都要检查事件目标很费力。如果只需要声明事件的名称,事件处理程序和CSS选择器来限制处理程序的调用时间,那就更好了。 jQuery为此提供了一个不错的API:
$(window).on('submit', '#arrange-dust-form', function (event) {
// do stuff on submit…
})
但是,如果您不使用jQuery或不希望使用jQuery,我们可以重新创建一个基本版本:
;(function () {
var eventTypes = [
'click', 'mouseover', 'mouseout', 'mousedown',
'mouseup', 'mouseenter', 'mouseleave', 'mousemove',
'keydown', 'keyup', 'submit', 'change', 'contextmenu',
'dblclick', 'input', 'focusin', 'focusout'
]
// Build structure for storing event handlers
var handlers = eventTypes.reduce(function (obj, eventType) {
obj[eventType] = {}
return obj
}, {})
// Add listeners for each event
eventTypes.forEach(function (eventType) {
window.addEventListener(eventType, function (event) {
var handlersForEvent = handlers[eventType]
for (var selector in handlersForEvent) {
if (event.target.matches(selector)) {
callHandlers(handlersForEvent[selector], event)
}
}
})
})
function callHandlers (eventHandlers, event) {
eventHandlers.forEach(function (handler) {
handler.call(null, event)
})
}
window.App = {
addEventListener: function (eventType, selector, handler) {
(handlers[eventType][selector] = handlers[eventType][selector] || [])
.push(handler)
}
}
})()
// Usage
App.addEventListener('submit', '#arrange-dust-form', function (event) {
// do stuff on submit…
})
这是一个简短的摘要。首先,它创建一个对象来存储每种事件类型的事件处理程序。然后,它为每种事件类型添加一个事件侦听器。该侦听器获取与事件类型匹配的处理程序,循环选择器,如果事件目标与选择器匹配,则调用处理程序。 App.addEventListener
获取给定事件类型和选择器的处理程序数组(如果不存在,则创建一个数组)并将处理程序推入该数组。在此系统中,可以为给定的事件类型/选择器添加多个处理程序。
一些警告:1. IE中不支持Element.matches
,因此您可能需要polyfill或添加一个包装函数来支持这一点。 2.这没有添加删除事件侦听器的方法,因此您可能希望添加它。
希望有帮助。