首页 / ASP.NET Core / 正文

[ASP.NET Core Razor Pages系列教程]ASP.NET Core Razor Pages中的Partial Views(部分视图)(04)

5972 发布于: 2018-10-22 读完约需16分钟

Partial Views (部分视图)

什么是Partial Views ?

Partial Views(之后统称:部分视图)是包含了HTML代码片段和服务端代码的Razor文件,它同样以.cshtml为扩展名。部分视图可以被包含在任意数量的页面或者布局中。部分视图可以用来将复杂的页面分解成更小的单元,从而减少复杂性,同时也可以在团队开发中被复用。

什么时候使用部分视图(Partial Views)

部分视图可以处理:

  • 将一个包含非常多的代码的Razor视图文件分解成多个小的部分视图文件。

  • 将通用部分的Razor视图代码提取到一个部分视图文件中,这样可以有效复用通用的代码片段。

提示:

  • 部分视图不应该用来管理和维护公共布局元素。通用的公共布局元素应该在_Layout.cshtml文件中来指定。
  • 如果代码片段中需要处理复杂的业务逻辑或者执行复杂的代码,也不推荐使用部分视图,而推荐使用视图组件(view component)

如何声明和使用部分视图(Partial Views)

在Razor Pages应用程序中,部分视图是以.cshtml为扩展名的代码标记文件,它通常被放在Razor Pages应用程序的[/Pages/]目录下。
在Razor Views应用程序开发中,我们可以有多种方式来引用部分视图。一个PageModel可以返回一个部分视图结果PartialViewResult。如:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorPagesDemoApplication.Pages.PartialPages
{
    public class IndexModel : PageModel
    {
        public IActionResult OnGet()
        {
            var partialView = new PartialViewResult();
            partialView.ViewName = "Partials/_menuPartial";
            return partialView;
        }
    }
}

以上的页面输出就只有部分视图Partials/_menuPartial.cshtml的内容。

注: 部分视图不像MVC视图或者Razor页面,它不执行_ViewStart.cshtml文件。
部分视图文件命名规则通常是以下划线开始的。当然这个命名约定不是必需的,你也可以不使用以下划线开始的命名规则,但是以下划线开始的命名规则更容易帮助我们从视觉上区别部分视图文件(Partial Views)和Razor Page。

.cshtml文件以下划线开始命名时,Razor Pages不会将这个视图文件作为Razor Pages页面来处理,即使文件的标记中包含@page指令。

从ASP.NET Core 2.1版本开始,官方更推荐的方式是使用Partial tag helper(部分视图标签),在Razor页面中的使用代码示例如下:

<partial name="_MenuPartial" />

以上的代码片段即演示了在Razor页面中使用一个部分视图_MenuPartial.cshtml的方式,其中的标签partial为ASP.NET Core 2.1+ 中内置的Tag Helper标签(关于什么是Tag Helper本文不作介绍)。partial标签内置了几个属性,外这里涉及到的name属性之外,还有如:for,model,view-data这三个属性。更多关于partial标签属性的介绍,请参考Partial Tag Helper

name属性的部分视图路径大小写不敏感

这里的Partials/_MenuPartial视图文件扩展名是缺省的,视图标签将按照View discovery的规则搜索指定目录中是否存在与Partials/_MenuPartial路径匹配的部分视图文件,如果搜索到了则将部分视图中的内容渲染并填充到引用这个部分视图的对应位置。

当然,我们也可以指定name属性的扩展名,如:

<partial name="_MenuPartial.cshtml" />

如上,指定了部分视图的扩展名,这时引用的部分视图就必须是位于当前Razor文件的相同目录,否则将无法渲该部分视图。

如果我们需要将部分视图的目录指定到从根目录开始,则可以使用(~/)或者(/)来引用,如下:

<partial name="~/Pages/Shared/Partials/_MenuPartial.cshtml" />
<partial name="/Pages/Shared/Partials/_MenuPartial.cshtml" />

最后,我们还可以使用相对目录来引用部分视图,如下:

<partial name="../Shared/Partials/_MenuPartial.cshtml" />

除了像上面提到的使用partial标签引用部分视图外,在Razor Pages中还提供了其他的方式,如:

@Html.Partial("Partials/_MenuPartial")

它和使用partial标签的效果基本差不多,但这种方式微软不推荐使用,因为容易发生死锁的情况。

当然,Html属性还提供了其他3种方法来引用部分视图:PartialAsync,RenderPartial以及RenderPartialAsync。以Async结尾的表示将以异步的方式加载部分视图,使用方式如下:

@await Html.PartialAsync("Partials/_MenuPartial")

其中,部分视图的路径与partial标签的路径规则相同,假设当前的Razor Pages文件位于[/Pages/PartialPages/Index.cshtml],部分视图位于[/Pages/Shared/Partials/_MenuPartial.cshtml]

1.带.cshtml扩展名的相对路径部分视图引用:

@await Html.PartialAsync("../Shared/Partials/_MenuPartial.cshtml")

2.从根目录的部分视图引用:

@await Html.PartialAsync("~/Pages/Shared/Partials/_MenuPartial.cshtml")

或者

@await Html.PartialAsync("~/Pages/Shared/Partials/_MenuPartial.cshtml")

最后,我们还可以使用RenderPartialAsync方法,这个方法不会返回IHtmlContect。它的数据流将直接被并输出到响应中。由于这个方法没有返回值,所以必须使用Razor代码块包裹起来,如下:

@{
    await Html.RenderPartialAsync("../Shared/Partials/_MenuPartial.cshtml");
    //或者 
    //await Html.RenderPartialAsync("Partials/_MenuPartial");
}

特别注意: 使用HtmlPartialRenderPartial两个同步方法时,在Visual Studio中会提示我们“使用IHtmlHelper.Partial容易造成程序死锁,考虑使用<partial>标签帮助类或者使用IHtmlHelper.PartialAsync代替” 。所以,在开发中,尽量不要使用Partial或者RenderPartial的同步方法,而使用异步方法PartialAsync或者RenderPartialAsync,微软官方还表示在后期的版本中将移除这两个同步方法。

部分视图的发现规则

当一个被引用的部分视图不包含.cshtml扩展名时,搜索这个部分视图的规则如下:

  1. 当前执行的Razor文件的目录
  2. 上一层目录
  3. /Shared
  4. /Pages/Shared
  5. /Views/Shared

如何向部分视图中传递参数或者对象等数据

使用部分视图支持我们传递数据(可以是用户自定义的实体对象或者ViewData),比如Html.PartialAsync()方法,有4个重载方法,允许我们传递一个或者两个参数,分别为:TModelViewDataDictionary

比如传递一个实体:

@await Html.PartialAsync("_PartialName", model)

比如传递一个ViewData:

@await Html.PartialAsync("_PartialName", customViewData)

下面以一个简单的示例来演示如何将数据传递到部分视图以及部分视图如何接收传递过来的参数和数据,示例的文件为[/Pages/PartialPages/Index.cshtml]

Index.cshtml.cs:

using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;

namespace RazorPagesDemoApplication.Pages.PartialPages
{
    public class IndexModel : PageModel
    {
        public List<string> Teches = new List<string>();
        public void OnGet()
        {
            Teches.AddRange(new[] 
            {
                "ASP.NET Core Razor Pages",
                "ASP.NET Core MVC",
                "ASP.NET Core Web API",
                "ASP.NET MVC"
            });
        }
    }
}

Index.cshtml:

@page
@model RazorPagesDemoApplication.Pages.PartialPages.IndexModel
@{
    ViewData["Title"] = "Partial Pages";
    Layout = "_Layout";
}

<h2>Partial page demo</h2>
<div class="row">
    <div class="col-md-3">
        @await Html.PartialAsync("Partials/_MenuPartial", Model.Teches,new ViewDataDictionary(ViewData) { {"UserName","Rector" } })
    </div>
    <div class="col-md-9">
        Content Area
    </div>
</div>

部分视图[/Pages/Shared/Partials/_MenuPatial.cshtml]

<p>Menu Area in menu partial page</p>
@model List<string>
<p>User name: @ViewData["UserName"]</p>
<ul class="list-unstyled">
    @foreach (var item in Model)
    {
        <li><a href="#">@item</a></li>
    }
</ul>

预览[/Pages/PartialPages/Index.cshtml]页面,将输出(仅摘取传递部分):

User name: Rector

   ASP.NET Core Razor Pages
   ASP.NET Core MVC
   ASP.NET Core Web API
   ASP.NET MVC

版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。

上一篇: [ASP.NET Core Razor Pages系列教程]Razor Pages 页面视图文件的组成和约束(03)

下一篇: [ASP.NET Core Razor Pages系列教程]ASP.NET Core Razor Pages中的Layout布局(05)

本文永久链接码友网 » [ASP.NET Core Razor Pages系列教程]ASP.NET Core Razor Pages中的Partial Views(部分视图)(04)

分享扩散:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册