我在脚本捆绑后在页面底部的_Layout.cshtml上使用@RenderSection("scripts", required: false)
。使用此布局的My View定义了脚本部分(@section scripts{ //script block}
)。当我通过整页调用从控制器动作渲染视图时,每件事都可以正常工作。
但是当我使用$ .ajax调用完成处理程序($('#container').html(result)
)在容器内呈现相同视图的内容时,_Layout.cshtml页面上定义的脚本部分不会在DOM上加载和执行。注意在这种情况下_Layout没有加载,因为调用是ajax并且布局页面已经在DOM上了,我不想再次加载布局页面来改善页面加载时间。我只关心加载子视图的内容。
请在下面找到设置
_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
@Styles.Render("~/Content/css")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Load Full", "LoadPartial", "Home")</li>
<li><a href="#" id="lnkMenu" data-url="@Url.Action("LoadPartial","Home")">Load via SPA</a></li>
</ul>
</div>
</div>
</div>
<div id="container" class="container body-content">
@RenderBody()
<hr />
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
<script src="~/Scripts/Common.js"></script>
@RenderSection("scripts", required: false)
</body>
</html>
调节器
public ViewResult LoadPartial()
{
return View("_LoadPartial");
}
_ViewStart.cshtml:
@{
Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
}
部分视图:_LoadPartial.cshtml
<div class="jumbotron">
<h2>Script loading demo</h2>
</div>
<p id="partial-id">Partial view content</p>
@section scripts
{
<script>
$(function () {
console.log("full");
$('#partial-id').css('color', 'blue');
});
</script>
}
使用ajax调用加载视图的Javascript代码
$(function () {
$('#lnkMenu').click(function () {
var url = $(this).data("url");
$.ajax({
url: url,
type: 'GET',
cache: false
}).done(function (result) {
$('#container').html(result);
});
});
});
现在,当我在第一种情况下使用布局加载页面时,它工作正常。但是,如果我尝试使用jquery ajax加载页面,则脚本部分不起作用。
=========================解决方案我试过====================== =========
为了解决这个问题,我尝试了以下解决方案,即在我的视图中,我根据条件加载脚本部分,如果请求是Ajax,则正常运行脚本,如果是带有布局的完整页面请求,则运行脚本部分。使用此解决方案,我的_LoadPartial.cshtml视图如下所示
<div class="jumbotron">
<h2>Script loading demo</h2>
</div>
<p id="partial-id">Partial view content</p>
@{
if (Request.IsAjaxRequest())
{
<script>
$(function () {
console.log("partial");
$('#partial-id').css('color', 'blue');
});
</script>
}
else
{
@section scripts
{
<script>
$(function () {
console.log("full");
$('#partial-id').css('color', 'blue');
});
</script>
}
}
}
这种解决方案在这两种情况下都能正常工作,但是解决方案的问题在于它违反了DRY原则,因为我必须在if
和block
中编写相同的脚本块。
有人知道处理这种情况的最佳方法是什么?
$(function(){});只是$(document).ready({})的简写;
$(document).ready只会在初始文档加载完成后触发一次。如果我正确理解你,你的流程如下:
$(document).ready将在步骤1和2之间调用。当您加载部分视图时,它已经被调用,并且不会因为您正在加载其他标记而再次调用。
我建议将$(function())代码更改为实际函数,并在ajax的success部分中调用它。
部分视图:_LoadPartial.cshtml
@section scripts
{
<script>
function changeTextColour() {
console.log("full");
$('#partial-id').css('color', 'blue');
};
</script>
}
JavaScript的
$(function () {
$('#lnkMenu').click(function () {
var url = $(this).data("url");
$.ajax({
url: url,
type: 'GET',
cache: false
}).done(function (result) {
$('#container').html(result);
changeTextColour();
});
});
});
=========================================================
如果需要更通用的解决方案,可以将部分视图标记作为字符串作为JSON对象的一部分返回,以便返回多个值。您需要以下方法:
public static string RenderPartialToString(Controller controller, string partialViewName, object model, ViewDataDictionary viewData, TempDataDictionary tempData)
{
ViewEngineResult result = ViewEngines.Engines.FindPartialView(controller.ControllerContext, partialViewName);
if (result.View != null)
{
controller.ViewData.Model = model;
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter output = new HtmlTextWriter(sw))
{
ViewContext viewContext = new ViewContext(controller.ControllerContext, result.View, viewData, tempData, output);
result.View.Render(viewContext, output);
}
}
return sb.ToString();
}
return String.Empty;
}
用法:
行动:
public ActionResult Action()
{
var viewModel = new WhateverTypeYourViewModelIs();
string partialHtml = RenderPartialToString(this, "PartialViewLocation.cshtml", viewModel, ViewData, TempData);
return Json(new { Html = partialHtml, Color = "Blue" });
}
使用Javascript:
$(function () {
$('#lnkMenu').click(function () {
var url = $(this).data("url");
$.ajax({
url: url,
type: 'GET',
cache: false
}).done(function (result) {
$('#container').html(result.Html);
changeTextColour(result.Color);
});
});
});
然后,您可以根据您正在呼叫的操作更改操作中的颜色。然后,您只需在页面加载时注册函数changeTextColor(),而不是在局部视图中。
希望其中一些有所帮助。