e.preventDefault();有多危险,可以用keydown / mousedown跟踪代替吗?

我正在为一个相当复杂的CRM制作跟踪脚本,以跟踪Google Analytics中的表单操作。 我正在努力平衡准确跟踪表单操作的愿望与永不阻止表单不工作的需要。

现在,我知道做这样的事情是行不通的。

$('form').submit(function(){ _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]); }); 

在有机会处理之前,DOM会卸载。

所以,很多示例代码推荐如下:

 $('form').submit(function(e){ e.preventDefault(); var form = this; _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]); //...do some other tracking stuff... setTimeout(function(){ form.submit(); }, 400); }); 

在大多数情况下这是可靠的,但它让我感到紧张。 如果e.preventDefault();之间发生了什么怎么e.preventDefault(); 当我开始触发基于DOM的提交时? 我完全打破了这个forms。

我一直在探索其他一些分析实现,我注意到这样的事情 :

 $('form').mousedown(function(){ _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]); }); $('form').keydown(function(e){ if(e.which===13) //if the keydown is the enter key _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]); }); 

基本上,不是中断表单提交,而是假设如果某人正在捣乱或按下Enter键而不是提交该表单而取代它。 显然,这会导致一定数量的误报,但它完全消除了对e.preventDefault(); 在我看来,这可以消除我可能阻止表单成功提交的风险。

那么,我的问题是:

  • 是否可以采用标准表单跟踪代码段并防止它完全阻止表单提交?
  • mousedown / keydown替代方案是否可行?
  • 是否有可能错过的提交案例? 具体来说,除了鼠标和键盘之外还有其他方式可以提交吗? 在开始卸载页面之前,浏览器是否总是有时间处理javascript?

他们在那里聚集了Googleplex非常明亮,他们有一天会想到这样的事情,因为这肯定会发生,现在,确实如此。 你为什么不试试这个:

 $('form').submit(function(e){ e.preventDefault(); var form = this; _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]); //...do some other tracking stuff... _gaq.push(function(){ form.submit(); }); }); 

那个_gaq.push thigamajigger按顺序执行它的元素,所以你应该开玩笑。

不,我不知道为什么我突然开始这么说。

我使用不同的方法,并在提交的页面中生成事件跟踪脚本。 您可以将其称为延迟事件跟踪

我写了一篇博客文章 ,其中详细介绍了我在后端操作中跟踪事件的方法。 它偏向于Java-Struts,但你可以得到一般的想法。

理由是我想在服务器端发生事后跟踪一些事情。 在这种情况下,表单由服务器提交和处理后。

我做了什么(非常总结):

  • 将事件存储在与会话关联的对象中(列表/队列)
  • 在下一页渲染时刷新这些事件(生成javascript并清空队列)

如果你必须让表格始终有效,但如果绝对必要,可以牺牲跟踪,你可以尝试/抓住它。

 $('form').submit(function(e){ try{ e.preventDefault(); var form = this; _gaq.push('_trackEvent', 'Form', 'Submit', $(this).attr('action')); //...do some other tracking stuff... setTimeout(function(){ form.submit(); }, 400); } catch (e) { form.submit(); } }); 

e.preventDefault()不必在函数调用的开头。 为什么不只是有一个if语句来validation一切是否正常工作,如果有的话只调用e.preventDefault() 。 如果链中的任何函数未返回预期结果,请将submitted变量设置为false ,并且不要阻止默认值。

对于任何异步(例如你的setTimeout ,这可能会有点难以处理,但是会有很多方法可以确定,具体取决于代码的样子。所以你可以检查if (_gaq.push)是否存在方法if (_gaq.push) (例如)。如果没有在每个浏览器中测试每个组合,你就无法100%确定,但我认为你可以得到一个非常令人满意的结果。

另一种方法:

 var pageTracker; _gaq.push(function() { pageTracker = _gat._getTrackerByName(); }); $('form').submit(function(e){ pageTracker._trackEvent('Form', 'Submit', $(this).attr('action')); }; 

我猜这种方式_trackEvent会同步,但我还没有测试过。

您是否有理由不能根据收到的POST从服务器端发出对Google Analytics的调用?

我不知道你的系统是什么内置的,但是例如,这个PHP项目会发出对GA的调用,从而消除了DOM卸载的问题,需要打破表单等等。

http://code.google.com/p/serversidegoogleanalytics/

我意识到你可能需要捕获一个cookie – 你可以在提交之前将值写入表单中的隐藏字段吗?

扩展@ Malvolio的答案:一旦gaq发送事件,队列中的下一个项目就会处理。 这意味着事件HTTP请求可能会在客户端中止,但GA将收到请求。 在响应完成之前,不要担心阻止脚本执行。 这是一个火灾和遗忘的场景。