10

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

<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>

我有一些像这样的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 中找到被点击的元素,完成功能。

4

5 回答 5

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 });
}

就是这样,你现在应该可以this用来引用源元素了。

于 2013-01-30T18:38:55.070 回答
4

您可以尝试像这样传递它:

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

进而:

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

或者干脆使用没有任何Ajax.*东西的jQuery:

<ul id="MainMenu">
    @foreach (var item in Model.MenuItems)
    {
        <li>
            @Html.ActionLink(
                item.Caption,
                item.ActionName,
                item.ControllerName,
                null,
                new { @class = "someLink" }
            )
        </li>
    }
</ul>

进而:

$(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;
    });
});
于 2011-07-08T20:37:17.567 回答
3

感谢大家提出的所有建议,Darin,尽管您的解决方案运行良好,但我想尝试使用内置的 Ajax 实用程序。

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

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

$.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"])
    });

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

Wich 作品创建,但在上下文中,“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);
}

现在,当您创建函数来处理这些事件时,您可以使用“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 来处理点击事件,嘿,你可能对这一切有更好的控制,

但我相信内置的东西也应该起作用。而不必弄乱它。所以我希望有人能证明我错了,实际上有更好的方法来做到这一点,或者把这个脚本放在一起的人可以改变它。

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

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

于 2011-07-09T11:54:00.643 回答
0

检查 event.srcElement 怎么样?

于 2011-09-28T00:03:01.440 回答
0

我有另一个解决方案,它使用 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');
}
于 2011-12-09T12:22:04.133 回答