关于jquery:如何加载包含JavaScript的局部视图?

How to load a partial view containing JavaScript?

在我的一个View页面中,我有一个asp.net mvc PartialView。 PartialView包含一些javascript(和jquery)。在我的asp.net主视图中,我使用ajax在div标签内加载PartialView,如下所示。也就是说,从控制器I返回PartialView("_ DonorEdit"),在我的主页面中,我使用javascript将Part标签的内容替换为PartialView响应。

1
    @{Html.RenderPartial("_DonorEdit");}

除了partialView(_DonorEdit)中包含的javascript之外,一切正常。因此,问题归结为 - 如何在div标签中嵌入javascript并仍然使其正常工作。

仅当从ajax调用返回部分视图时,才会出现此问题。在上面的代码中,如果我直接包含PartialView(在非ajax请求上),那么javascript正常工作。但是如果我稍后使用ajax请求替换div的内容,则PartialView中包含的javascript不起作用。嵌入式javascript根本不会与"部分视图"一起显示。所以似乎有一些其他原因,为什么在ajax请求成功之后,部分视图中嵌入的javascript不会传递给浏览器。

我的javascript代码的一部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<script type=...>
//Date Picker. This works. I get Calendar popup as expected

$(document).ready(function () {
    $("#Donor_BirthDate").datepicker({
        dateFormat:"dd-mm-yy",
        changeMonth: true,
        changeYear: true,
        yearRange:"-75:+0"
    });

    $("#Donor_DateLastDonated").datepicker({
        dateFormat:"dd-mm-yy",
        changeMonth: true,
        changeYear: true,
        yearRange:"-20:+1"
    });
});


//Dropdown handler. Does not make it in my final View.

function residenceStateChanged(e) {
    var url = '@Url.Action("_GetCities","DropDown")';
    var cmbResidenceCityId = $('#ResidenceCityId').data('tDropDownList');
    cmbResidenceCityId.loader.showBusy();

    $.ajax({
        type: 'GET',
        url: url,
        data: { StateId: e.value, AddSelectOption: true, SelectOption: 'Select' },
        traditional: true,
        success: function (resp, textStatus, jqXHR) {
            cmbResidenceCityId.dataBind(resp);
            cmbResidenceCityId.select(0);
            cmbResidenceCityId.trigger.change();
        },
        error: function (jqXHR, textStatus, errorThrown) {
            alert(jqXHR.responseText);
        },
        complete: function () {
            cmbResidenceCityId.loader.hideBusy();
        }
    });
}

....//Some other code omitted. Does not make it in final view.


解决问题的另一种方法是在控制器中渲染局部视图,返回json对象中的html作为ajax调用结果。

在Controller中,您可以使用通用方法呈现部分视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private string RenderPartialView(string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
    {
        viewName = this.ControllerContext.RouteData.GetRequiredString("action");
    }
    this.ViewData.Model = model;
    using (var sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(this.ControllerContext, viewName);
        var viewContext = new ViewContext(this.ControllerContext, viewResult.View, this.ViewData, this.TempData, sw);
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
        return sw.GetStringBuilder().ToString();
    }
}

然后,您将必须向控制器添加一个新的操作方法,该方法返回渲染视图,即:

1
2
3
4
5
6
7
public JsonResult GetDonorEdit()
{
    return Json(new
    {
        DonorEditContent = RenderPartialView("_DonorEdit", null)
    });
}

在客户端,可以将ajax调用更改为以下内容:

1
2
3
4
5
6
7
8
9
10
11
$.ajax({
    type:"POST",
    url:"GetDonorEdit",  // get the correct url of GetDonorEdit action
    cache: false
})
.success(function (result) {
    $("#content").html(result.DonorEditContent);
})
.error(function (xhr, errStatus, errThrown) {
    //...
});

我使用这种技术,因为通常必须在同一个ajax调用中返回多个局部视图,并且还因为它在部分视图中正确执行了javascript代码。

希望能帮助到你。


我相信你的问题与这个问题有关:

在一个AJAX调用中调用html内部的jQuery函数

看看它是否有帮助。


如果您在多个页面中使用此功能,为什么不将它包含在脚本文件(可能名为_DonorEdit.js)中,并包括那些使用部分的页面?

您可以使用require.js之类的东西来简化对此的管理。
作为require.js的替代,您可以使用像Cassette.net这样的资产捆绑来管理页面的依赖关系以及您通过ajax加载的任何部分。

然后,就像在ajax成功处理程序内部的绑定/触发器调用一样,您可以注册部分所需的任何事件/处理程序。

从长远来看,你可能想要看看的是knockout.js:在_DonorEdit.js文件中创建一个viewmodel,它与你局部返回的模板绑定,可以非常强大和可维护。如果您仍然希望渲染部分服务器端的所有数据,您仍然可以在某种程度上利用knockout的事件绑定。


在你的ajax成功部分调用javascript函数