如何在MVC3 Ajax.ActionLink OnBegin,OnComplete Events中使用$(this)

我的控制器创建了这样的链接列表

 

我有一些像这样的JavaScript

 function BeginUpdatePage() { $("#MainMenu li").removeClass('selected'); $(this).parent().addClass('selected'); $("#pageBody").fadeTo('slow', 0.5); } function EndUpdatePage() { $("#pageBody").fadeTo('slow', 1); } function FailUpdatePage() { alert('There has been an error loading this page please try again.'); } 

在BeginUpdatePage函数第1行和第3行执行正常,但第2行“$(this).parent()。addClass(’selected’);” 不会做任何事……(我已经在我的CSS中宣布了这个课程)。

我查看了Jquery文档( Jquery.ajax() )它说“this”是被点击的元素。 我还检查了默认情况下在我的项目中的“jquery.unobtrusive-ajax.js”。 执行我的函数时,此文件也会传递“this”。

 "result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this,arguments);" 

我在这里做错了什么……我见过其他使用过这种技术的例子 ,但我一整天都失败了!

如何在Begin,complete函数中找到被单击的元素。

更新2014年1月20日 :不显眼的ajax脚本的官方3.1版本包含此更改,并与MVC 5.1版本(1月17日)同时发布。 去检查看看:-)

原始回复

我偶然发现了这一点 ,以达到你想要的结果。 很简单。

绕过jquery.unobtrusive-ajax.js文件大约第100行,添加这一行代码。

 options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); options.context = element; // <--- Add this line method = options.type.toUpperCase(); if (!isMethodProxySafe(method)) { options.type = "POST"; options.data.push({ name: "X-HTTP-Method-Override", value: method }); } 

就是这样,你现在应该能够使用this来引用源元素。

您可以尝试这样传递:

 OnBegin = "function() { BeginUpdatePage(this); }" 

然后:

 function BeginUpdatePage(element) { $("#MainMenu li").removeClass('selected'); $(element).parent().addClass('selected'); $("#pageBody").fadeTo('slow', 0.5); } 

或者只是使用jQuery而不使用任何Ajax.*东西:

  

然后:

 $(function() { $('.someLink').click(function() { var link = $(this); $.ajax({ url: this.href, beforeSend: function() { $("#MainMenu li").removeClass('selected'); $(link).parent().addClass('selected'); $("#pageBody").fadeTo('slow', 0.5); }, complete: function() { $("#pageBody").fadeTo('slow', 1); }, success: function(result) { $('#pageBody').html(result); }, error: function() { alert('There has been an error loading this page please try again.'); } }); return false; }); }); 

感谢大家提出的所有建议,Darin,虽然您的解决方案完美无缺,但我想尝试使用内置的Ajax实用程序。

在查看Jquery.Ajax()Docs并检查“jquery.unobtrusive-ajax.js”之后,我找到了一个解决方法。这更像是一个Hack而不是正确使用,我不确定是谁放了“jquery.unobtrusive-ajax。 js“汇总在一起,但如果有人知道如何通过电子邮件发送给他们,可能会向他们发送一个指向此页面的链接:-)

这是“jquery.unobtrusive-ajax.js”中有趣的部分,在这个函数“function asyncRequest(element,options)”中

 $.extend(options, { type: element.getAttribute("data-ajax-method") || undefined, url: element.getAttribute("data-ajax-url") || undefined, beforeSend: function (xhr) { var result; asyncOnBeforeSend(xhr, method); result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments); if (result !== false) { loading.show(duration); } return result; }, complete: function () { loading.hide(duration); getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments); }, success: function (data, status, xhr) { asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments); }, error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]) }); 

当这段代码在发送,完成,错误之前的每一步调用apply方法时,它传入两个perams,“this”和“arguments”……

Wich工作创建,但在上下文中“this”是XHR(XMLHttpRequest)而不是被点击的元素…通过检查函数头,您可以看到它将XHR对象作为第一个参数传递。 那么为什么我们还需要它作为调用上下文呢?

我的解决方案……更改“jquery.unobtrusive-ajax.js”和“jquery.unobtrusive-ajax-min.js”文件……

而不是在apply方法上传递“this”(XHR),让我们发送实际的元素!

所以整个function现在看起来像这样:

 function asyncRequest(element, options) { var confirm, loading, method, duration; confirm = element.getAttribute("data-ajax-confirm"); if (confirm && !window.confirm(confirm)) { return; } loading = $(element.getAttribute("data-ajax-loading")); duration = element.getAttribute("data-ajax-loading-duration") || 0; $.extend(options, { type: element.getAttribute("data-ajax-method") || undefined, url: element.getAttribute("data-ajax-url") || undefined, beforeSend: function (xhr) { var result; asyncOnBeforeSend(xhr, method); result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments); if (result !== false) { loading.show(duration); } return result; }, complete: function () { loading.hide(duration); getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments); }, success: function (data, status, xhr) { asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments); }, error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]) }); options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); method = options.type.toUpperCase(); if (!isMethodProxySafe(method)) { options.type = "POST"; options.data.push({ name: "X-HTTP-Method-Override", value: method }); } $.ajax(options); } 

现在,当您创建处理这些事件的函数时,可以使用“this”来获取实际元素。

例:

 function BeginUpdatePage(xhr) { $("#MainMenu li").removeClass('selected'); $(this).parent().addClass('selected'); $("#pageBody").fadeTo('slow', 0.5); } function EndUpdatePage(xhr,status) { $("#pageBody").fadeTo('slow', 1); } function FailUpdatePage(data,status,xhr) { alert('There has been an error loading this page please try again.'); } 

现在对于某些人来说,我更容易使用Darin的解决方案,只需编写自己的Jquery来处理点击事件,嘿,你可能有更好的控制权,

但我相信内置的东西也应该有效。 不必乱用它。 因此,我希望有人可以certificate我是错的,并且实际上有更好的方法可以做到这一点,或者将这个脚本放在一起的人可以改变它。

除非他们有充分的理由这样做吗? 解释欢迎:-)

再次感谢所有对此问题提出好建议的人,我希望这对未来的人们有所帮助。

检查event.srcElement怎么样?

我有另一种解决方案,它使用AJAX URL来选择被点击的原始链接。 只有一个具有确切URL的ActionLink,此解决方案才能正常工作:

 function BeginUpdatePage() { // Get the URL that will be posted to var targetUrl = this.url; var sourceLink = null; // loop through all action links applicable $('#MainMenu a').each(function () { var href = $(this).attr('href'); // the targetUrl contains the entire URL - including http:// // so we need to do an indexOf to see if the href is contained // within the target URL if (targetUrl.indexOf(href) > -1) { sourceLink = $(this); return false; } }); // we've now got the link that was clicked - do with it as you wish... sourceLink.parent().addClass('selected'); }