如何加载包含 JavaScript 的局部视图?

Posted

技术标签:

【中文标题】如何加载包含 JavaScript 的局部视图?【英文标题】:How to load a partial view containing JavaScript? 【发布时间】:2011-11-11 06:22:02 【问题描述】:

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

<div class="content" id="content">
    @html.RenderPartial("_DonorEdit");   
</div>

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

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

我的javascript代码部分

<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.
</script>

【问题讨论】:

javascript 是什么样的? 你能明确定义什么是行不通的吗?在 renderpartial 之后,javascript 的哪一部分不起作用? @Gisli,我的部分视图中有一些下拉菜单。为了处理这些下拉菜单的 onchange 之类的事件,我有一些 javascript 代码,这是有问题的代码(即不工作,因为它包含在 div 标签中)。由于部分视图包含在许多主页中,因此我将此 javascript 代码嵌入到包含的文件(部分视图)中,而不是在我的所有主视图中复制它。 JavaScript 函数是否包含在 jQuery document.ready() 函数或类似函数中,因为 document.ready() 在加载部分文件之前很久就会触发。 @Tom,事实上它是另一种方式。 document.ready() 中包含的 JQuery 代码可以正常工作。但是在 jquery document.ready() 之外定义的其他函数根本不会出现在页面中。这是我得到参考错误的地方(“未定义函数 xxx”)。我应该在我的问题中粘贴我的 javascript 代码吗? 【参考方案1】:

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

Calling a jQuery function inside html return from an AJAX call

看看有没有帮助。

【讨论】:

起初我以为这样可以解决问题,所以我尝试将数据类型设置为“html”。但我仍然得到 MissingReference(在 chrome 中),说明 javascript 函数不可用。 你能看到使用 Firebug 的代码中的 JavaScript 函数吗?您能否检查从 AJAX 调用返回的 HTML(同样,使用 Firebug 和 Net 选项卡)?如果您的 AJAX 调用实际上并未返回该函数,则部分视图有问题。 我使用 fiddler 检查来自服务器的响应。 PartialView 中定义的 javascript 函数是服务器响应的一部分。所以服务器代码很好,它返回正确的响应。问题是当我在渲染视图中检查 html 时,我看不到这些函数。局部视图是 Telerik 模态窗口的一部分。我希望不是因为telerik窗口出现这个问题(理想情况下不应该)。所以简而言之,响应包含嵌入的javascript,但呈现的html没有它。【参考方案2】:

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

在Controller中,你可以有一个通用的方法来渲染一个局部视图:

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

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

public JsonResult GetDonorEdit()

    return Json(new 
     
        DonorEditContent = RenderPartialView("_DonorEdit", null) 
    );

在客户端,ajax 调用可以改成这样:

$.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 代码。

希望对你有帮助。

【讨论】:

这行viewName = this.ControllerContext.RouteData.GetRequiredString("action");是什么意思?动作变量将持有什么? 获取当前动作名称,如果未指定viewName,则假定视图与动作名称相同。【参考方案3】:

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

【讨论】:

有些函数是基于事件的。我不能简单地调用 javascript 函数。每当我的一个下拉菜单中发生诸如 onchange 之类的事件时,就会执行这些函数。 根据您的 javascript 查找的内容,OnSuccess 通常可以正常工作。您也可以尝试在 $(document).ready of you partial 中包含脚本。【参考方案4】:

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

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

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

从长远来看,您可能想要查看的东西是 knockout.js:在该 _DonorEdit.js 文件中创建一个视图模型,该文件绑定到您的部分返回的模板可以非常强大且可维护.如果您仍然希望为部分服务器端呈现所有数据,您仍然可以在某种程度上利用淘汰赛的事件绑定。

【讨论】:

以上是关于如何加载包含 JavaScript 的局部视图?的主要内容,如果未能解决你的问题,请参考以下文章

使用 JQuery 重新加载局部视图

javascript 加载的局部视图 MVC 中发生错误时重定向到错误页面

如何使用JavaScript加载部分视图[重复]

如何防止部分视图中的脚本多次加载并在同一页面中多次使用部分时导致错误

动态局部视图 + jquery 表单劫持 + 客户端验证 = 不工作

重新加载后如何将数据传递给局部视图