有没有办法从局部视图中添加对页面的 CSS 引用,并让它们在页面中呈现<head>
(根据HTML 4.01 规范的要求)?
6 回答
如果您使用的是 MVC3 和 Razor,将每页项目添加到您的部分的最佳方法是:1)从布局页面中调用 RenderSection() 2)在子页面中声明相应的部分:
/Views/Shared/_Layout.cshtml:
<head>
<!-- ... Rest of your head section here ... ->
@RenderSection("HeadArea")
</head>
/Views/Entries/Index.cshtml:
@section HeadArea {
<link rel="Stylesheet" type="text/css" href="/Entries/Entries.css" />
}
生成的 HTML 页面随后包含如下所示的部分:
<head>
<!-- ... Rest of your head section here ... ->
<link rel="Stylesheet" type="text/css" href="/Entries/Entries.css" />
<head>
您还可以使用 Telerik 的 MVC 开源控件并执行以下操作:
<%= Html.Telerik().StyleSheetRegistrar()
.DefaultGroup(group => group
.Add("stylesheet.css"));
在头部和
<%= Html.Telerik().ScriptRegistrar()
.DefaultGroup(group => group
.Add("script.js"));
在页面底部的脚本部分。
您可以继续在任何视图或部分视图上添加脚本,它们应该可以工作。
如果您不想使用该组件,您总是可以从那里激发自己并做一些更自定义的事情。
哦,使用 Telerik,您还可以选择组合和压缩脚本。
您可以在一个 javascript 块中加载部分视图,该块的样式下降到头部,但考虑到您可能出于同样的原因希望在头部部分中使用 javascript 块,这将是愚蠢的。
不过,我最近发现了一些很酷的东西。您可以将部分视图序列化为字符串并将其作为 JSON 对象的一部分发送回客户端。这使您还可以与视图一起传递其他参数。
您可以使用 JQuery 和 ajax 获取 JSON 对象并使用部分视图加载它,然后另一个 JSON 属性可能是您的样式块。JQuery 可以检查您是否返回了样式块,如果是,则将其放入 head 部分。
就像是:
$.ajax(
{
url: "your/action/method",
data: { some: data },
success: function(response)
{
$('#partialViewContainer).html(response.partialView);
if (response.styleBlock != null)
$('head').append(response.styleBlock);
}
});
您可以使用 aHttpModule
来操作响应 HTML 并将任何 CSS/脚本引用移动到适当的位置。这并不理想,而且我不确定性能影响,但它似乎是解决问题的唯一方法,无需 (a) 基于 javascript 的解决方案,或 (b) 违反 MVC 原则。
另一种违反 MVC 原则的方法是使用 ViewModel 并响应页面的 Init 事件来设置所需的 css/javascript(即 myViewModel.Css.Add(".css") 并在您的头部呈现viewmodel 上的 css-collection 的内容。
为此,您创建一个基础视图模型类,您的所有其他模型都继承自该类,ala
public class BaseViewModel
{
public string Css { get; set; }
}
在您的母版页中,您将其设置为使用此视图模型
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<BaseViewModel>" %>
和你的头部分,你可以写出 Css 属性的值
<head runat="server">
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
<%= Model.Css %>
</head>
现在,在您的局部视图中,您需要拥有这段代码,这在 MVC 中有点难看
<script runat="server">
protected override void OnInit(EventArgs e)
{
Model.Css = "hej";
base.OnInit(e);
}
</script>
以下仅在启用 javascript 时才有效。这是我用于您提到的场景的一个小帮手:
// standard method - renders as defined in as(cp)x file
public static MvcHtmlString Css(this HtmlHelper html, string path)
{
return html.Css(path, false);
}
// override - to allow javascript to put css in head
public static MvcHtmlString Css(this HtmlHelper html,
string path,
bool renderAsAjax)
{
var filePath = VirtualPathUtility.ToAbsolute(path);
HttpContextBase context = html.ViewContext.HttpContext;
// don't add the file if it's already there
if (context.Items.Contains(filePath))
return null;
// otherwise, add it to the context and put on page
// this of course only works for items going in via the current
// request and by this method
context.Items.Add(filePath, filePath);
// js and css function strings
const string jsHead = "<script type='text/javascript'>";
const string jsFoot = "</script>";
const string jsFunctionStt = "$(function(){";
const string jsFunctionEnd = "});";
string linkText = string.Format("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\"></link>", filePath);
string jsBody = string.Format("$('head').prepend('{0}');", linkText);
var sb = new StringBuilder();
if (renderAsAjax)
{
// join it all up now
sb.Append(jsHead);
sb.AppendFormat("\r\n\t");
sb.Append(jsFunctionStt);
sb.AppendFormat("\r\n\t\t");
sb.Append(jsBody);
sb.AppendFormat("\r\n\t");
sb.Append(jsFunctionEnd);
sb.AppendFormat("\r\n");
sb.Append(jsFoot);
}
else
{
sb.Append(linkText);
}
return MvcHtmlString.Create( sb.ToString());
}
用法:
<%=Html.Css("~/content/site.css", true) %>
如上所述,仅在启用 javascript 的情况下才对我有用,从而稍微限制了它的有用性。