我找到了一个更加优雅的解决方案。
我正在使用 Styles.RenderFormat(format, bundle)
。
我有一个名为 BundlesFormats
的类,其中包含一个叫做 PRINT
的属性,并且我是这样使用它的:
public class BundlesFormats
{
public const string PRINT = @"<link href=""{0}"" rel=""stylesheet"" type=""text/css"" media=""print"" />";
}
还有在cshtml中:
@Styles.RenderFormat(BundlesFormats.PRINT, "~/bundles/Content/print")
好吧,这是一个不太美观的hack,但希望团队能在下一个版本中添加一种内置的方法来完成它。
这就是我解决它的方法,保持缓存字符串并仍然能够向标签添加媒体属性。
@{
var cssMediaBundleUrl = BundleTable.Bundles.ResolveBundleUrl("~/stylesheets/mediacss", true);
}
<link href="@cssMediaBundleUrl" rel="stylesheet" type="text/css" media="screen" />
我猜我可以把这个变成一个HTML辅助器,稍后会这样做并进行编辑。
另一个解决此问题的选择,而不会影响调试能力,可能是:
public static IHtmlString Render(string path, IDictionary<string, object> htmlAttributes)
{
var attributes = BuildHtmlStringFrom(htmlAttributes);
#if DEBUG
var originalHtml = Styles.Render(path).ToHtmlString();
string tagsWithAttributes = originalHtml.Replace("/>", attributes + "/>");
return MvcHtmlString.Create(tagsWithAttributes);
#endif
string tagWithAttribute = string.Format(
"<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\"{1} />",
Styles.Url(path), attributes);
return MvcHtmlString.Create(tagWithAttribute);
}
我所做的就是将给定的HTML属性附加到标签的末尾(在调试模式下),或将其附加到唯一链接标签的末尾(当启用缩小/捆绑时)。
在视图中的使用:
@Bundles.Render("~/css/print", new { media = "print" })
代码的其余部分:
public static IHtmlString Render(string path, object htmlAttributes)
{
return Render(path, new RouteValueDictionary(htmlAttributes));
}
private static string BuildHtmlStringFrom(IEnumerable<KeyValuePair<string, object>> htmlAttributes)
{
var builder = new StringBuilder();
foreach (var attribute in htmlAttributes)
{
builder.AppendFormat(" {0}=\"{1}\"", attribute.Key, attribute.Value);
}
return builder.ToString();
}
我写了一篇关于这个主题的博客文章:http://danielcorreia.net/blog/quick-start-to-mvc4-bundling/。
不幸的是,目前还没有很好的方法来钩入标签的渲染。我们考虑添加一个钩子,以便您可以添加自己的方法来渲染每个脚本/样式标签。听起来我们确实需要这样做。添加起来应该很简单,我将创建一个工作项来启用此方案...
作为一种临时解决方案,如果您愿意放弃Styles.Render给您带来的调试/发布功能,您可以使用Styles.Url渲染对捆绑包的引用,这样只会给您捆绑包的网址,您可以将其嵌入到自己的标签中。
为什么不直接使用@media print?请查看http://www.phpied.com/5-years-later-print-css-still-sucks/。
在BundleConfig.cs中:
//Print css must be a separate bundle since we are going to render it with a media=print
Bundles.Add(new StyleBundle("~/bundles/printCSS").Include("~/Content/Print.css"));
主页面:
<asp:Literal runat="server" ID="litCssPrint" />
主控页面代码文件:
litCssPrint.Text = Styles.RenderFormat(@"<link href=""{0}"" rel=""stylesheet"" type=""text/css"" media=""print"" />", "~/bundles/printCSS").ToHtmlString();
我进一步采纳了Adam Tal的建议。
为了可读性,我可能有点过度编码,但我创建了一个静态类来模拟Styles.Render
格式。
public static class StyleExtensions
{
public enum Format
{
Async,
Preload,
}
public static IHtmlString Render(string contentPath, Format format)
{
switch (format)
{
case Format.Async:
return contentPath.ToAsyncFormat();
case Format.Preload:
return contentPath.ToPreloadFormat();
default:
return new HtmlString(string.Empty);
}
}
public static IHtmlString RenderAsync(string contentPath)
{
return contentPath.ToAsyncFormat();
}
public static IHtmlString RenderPreload(string contentPath)
{
return contentPath.ToPreloadFormat();
}
public static IHtmlString ToAsyncFormat(this string contentPath)
{
return Styles.RenderFormat("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" media=\"print\" onload=\"this.media='all';this.onload=null;\">", contentPath);
}
public static IHtmlString ToPreloadFormat(this string contentPath)
{
return Styles.RenderFormat("<link rel=\"preload\" href=\"{0}\" as=\"style\" onload=\"this.rel='stylesheet';this.onload=null;\">", contentPath);
}
}
我可能会删除直接构造函数或枚举构造函数,你也可以将字符串扩展放在方法内部,具体取决于哪种方式更有意义,但你需要相应地调用以下任一方式:
@StyleExtensions.Render("~/Content/bundle-bootstrap", StyleExtensions.Format.Preload)
@StyleExtensions.Render("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&display=swap", StyleExtensions.Format.Preload)
@StyleExtensions.Render(Url.Content("~/Content/Styles/Primary.min.css"), StyleExtensions.Format.Async)
或者
@StyleExtensions.RenderPreload("~/Content/bundle-bootstrap")
@StyleExtensions.RenderPreload("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&display=swap")
@StyleExtensions.RenderAsync(Url.Content("~/Content/Styles/Primary.min.css"))
这么复杂,为什么不使用:
bundles.Add<StylesheetBundle>("~/Css/site.css", b => b.Media = "screen");
?
Microsoft.AspNet.Web.Optimization.1.1.3
不包含通用的Add方法。 - janv8000Add<T>()
和StylesheetBundle
。 - SandRock