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

Mic*_*ake 10 jquery asp.net-mvc-3 unobtrusive-ajax

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

<ul id="MainMenu">
@foreach (var item in Model.MenuItems)
{
    <li>@Ajax.ActionLink(item.Caption,
    item.ActionName,
    item.ControllerName,
    new AjaxOptions
    {
        UpdateTargetId = "pageBody",
        OnBegin = "BeginUpdatePage",
        OnComplete = "EndUpdatePage",
        OnFailure = "FailUpdatePage"
    })
    </li>
}
</ul>
Run Code Online (Sandbox Code Playgroud)

我有一些像这样的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.');
}
Run Code Online (Sandbox Code Playgroud)

在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);"
Run Code Online (Sandbox Code Playgroud)

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

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

Nic*_*cht 10

更新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 });
}
Run Code Online (Sandbox Code Playgroud)

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


Mic*_*ake 3

谢谢你们的所有建议,Darin,尽管您的解决方案工作得很好,但我想尝试使用内置的 Ajax 实用程序。

在查看Jquery.Ajax() 文档并检查“jquery.unobtrusive-ajax.js”后,我找到了解决方法,这更像是一种黑客而不是正确使用,我不确定是谁把“jquery.unobtrusive-ajax.js”放在了。 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"])
    });
Run Code Online (Sandbox Code Playgroud)

当此代码在 beforeSend、Complete、error 的每个步骤上调用apply方法时,它会传入两个 peram,“this”和“arguments”...

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

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

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

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

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);
}
Run Code Online (Sandbox Code Playgroud)

现在,当您创建函数来处理这些事件时,您可以使用“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.');
}
Run Code Online (Sandbox Code Playgroud)

现在对于某些人来说,采用 Darin 的解决方案会更容易,只需编写自己的 Jquery 来处理单击事件,嘿,您可能可以更好地控制这一切,

但我相信内置的东西也应该可以工作。无需打扰它。所以我希望有人能证明我错了,实际上有更好的方法来做到这一点,或者编写这个脚本的人可以改变它。

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

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