什么是Layout ?
在现代的Web网站应用程序开发中,一个页面通常包含了几个部分(区域),如:头部,左侧导航,右侧主内容显示区域以及底部信息等等。在多页面开发过程中,除了右侧主内容显示区域的内容各不相同外,其他部分的内容都是相同的。这时,我们就需要使用Layout Page(布局页面)来装载相同的部分,不同的内容显示区域由每个页面自己根据实际情况渲即可。比如有如下的布局结构(图片来自微软ASP.NET Core文档):
如果你对ASP.NET MVC熟悉,那么本文理解起来是非常容易的。因为Razor Pages中的布局页面和ASP.NET MVC中的布局页面相似。
在布局页面中,我们可以将通用的HTML结构代码(比如:CSS样式文件的引用,Javascript脚本文件的引用等)集中引用,这样可以有效地管理和维护通用的HTML代码,避免重复写同样的代码。假设不使用布局页面,如果有一天需要修改网站中所有页面的导航,我们得去修改每个页面的导航代码。但在使用了布局页面之后,就只需要修改布局页面中一处导航代码即可,大大方便了代码的维护。
官方约定,ASP.NET Core Razor Pages项目中的布局页面默认以_Layout.cshtml
命名,并存放在项目的指定目录[/Pages/Shared/_Layout.cshtml]中,目录结构如下:
在一个Razor Pages应用程序中,可以不需要创建布局页面,也可以创建一个或者多个布局页面,只需要分别使用不同的布局页面文件名即可。
官方默认生成的布局页面_Layout.cshtml
内容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebApplication1</title>
<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">WebApplication1</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
</ul>
@await Html.PartialAsync("_LoginPartial")
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© 2018 - WebApplication1</p>
</footer>
</div>
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("scripts", required: false)
</body>
</html>
一个简化版本的布局页面可能是这样的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<link href="/css/site.css" rel="stylesheet" type="text/css" />
</head>
<body>
@RenderBody()
</body>
</html>
这个简化版的布局页面中只包含了@RenderBody()
方法,其实这里的@RenderBody()
你可以把它看成是一个占位符,当Razor内容页面引用这个_Layout.cshtml
布局页面时,会将内容页面的内容填充到@RenderBody()
的位置。
注意: 一个布局页面中只能同时包含一个
@RenderBody()
方法
如何引用Layout布局页面?
在Razor视图页面中,有一个叫Layout
的属性,我们可以通过设置这个Layout
属性来指定某个Razor视图页面需要使用的布局页面模板,如:
@{
Layout = "_Layout";
}
其中,Layout
的路径可以是完整的路径(如:~/Pages/Shared/_Layout.cshtml),也可以是以面示例的简写方式_Layout
,如果使用简写的方式指定布局页面,那么Razor视图引擎将使用内置的视图搜索器搜索指定的布局文件。首先会搜索当前页面所在的目录,然后搜索Shared
目录,搜索方式与部分视图的搜索方式是一致的。
Sections
在布局页面中,包含了@RenderBody()
方法,但这个方法只能在页面文件中渲染一个位置,如果我们需要在页面文件中渲多个位置,是不是就不行了呢?
这时Sections
就应该派上用场了。Sections
对应的方法为:@RenderSection
,在需要的地方使用如下方式标记:
@RenderSection("Scripts", required: false)
这里的RenderSection(...)
有两个参数,第一个参数为占位名称,第二个参数表示是否是必须的,如果为true
,那么在使用了这个布局页面的Razor内容页面中必须指定Scripts
的section
,如下:
@section Scripts {
<script type="text/javascript" src="/scripts/main.js"></script>
}
在某些情况下,我们还需要判断Razor页面是否指定了某个section
,如果没有指定,则在_Layout
中设置默认的内容,这时可以使用IsSectionDefined()
方法,示例如下:
@if(IsSectionDefined("OptionalSection"))
{
@RenderSection("OptionalSection")
}
else
{
// 默认的内容
}
注意:
IsSectionDefined()
方法只能在布局页面中使用。
版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。
发表评论
登录用户才能发表评论, 请 登 录 或者 注册