下面我将详细解释这个概念,并提供一个基于 ASP.NET MVC 的具体实现示例,因为这个场景是该框架最常见的应用之一。

核心概念:模板页与内容页
我们明确一下这两个概念在 MVC 中的角色:
- 模板页:通常指网站的布局页,
_Layout.cshtml,它定义了网站的整体结构,如页头、导航栏、页脚、侧边栏等,它包含了一些“占位符”(@RenderBody(),@RenderSection()),用来动态插入具体页面的内容。 - 内容页:指具体的 Action 对应的 View,
Home/Index.cshtml,这个页面本身不包含完整的 HTML 结构(如<html>,<head>,<body>),它只包含需要显示在模板页@RenderBody()占位符中的核心内容。
传统全页面刷新流程:
浏览器请求 /Home/Index -> 服务器返回完整的 HTML(包含 _Layout 和 Index 的内容) -> 浏览器重新渲染整个页面。
局部刷新目标:
我们希望只更新 @RenderBody() 对应的部分,而页头、导航栏、页脚等保持不变,从而提供更流畅、更快的用户体验。
实现局部刷新的技术方案
实现局部刷新主要有两种主流技术:

jQuery + AJAX (经典且易于理解)
这是最传统、最广泛使用的方法,其核心流程是:
- 初始加载:第一次访问页面时,服务器仍然返回完整的 HTML 页面(包含
_Layout),让用户看到整个网站。 - 触发局部刷新:用户执行某个操作(如点击链接、提交表单、选择下拉框等)。
- AJAX 请求:使用 JavaScript (如 jQuery 的
$.ajax或$.get) 向服务器发送一个异步请求,这个请求通常指向一个特定的 Action。 - 服务器返回:服务器接收到请求后,只生成并返回内容页的 HTML 片段,而不是完整的布局页。
- 前端渲染:JavaScript 接收到这个 HTML 片段后,用它替换掉页面中
<div id="main-content">(或其他容器) 的innerHTML。
关键点:如何让服务器只返回内容页的 HTML 而不带布局?答案是 Partial View (部分视图)。
ASP.NET MVC AJAX Helper (更“MVC”的方式)
ASP.NET MVC 提供了一套内置的 AJAX Helper,可以简化方案一的很多手动操作,它基于 Microsoft AJAX Library 和 jQuery。
Ajax.ActionLink:生成一个可以发起 AJAX 请求的链接。Ajax.BeginForm:生成一个可以提交 AJAX 请求的表单。AjaxOptions:配置 AJAX 请求的各种选项,如更新目标、加载提示、成功回调等。
这种方式本质上还是 AJAX,但将大量的 JavaScript 代码封装到了 Razor 语法中,使代码更整洁。

具体实现示例 (ASP.NET MVC + jQuery)
假设我们有一个简单的博客首页,顶部有导航栏,中间是文章列表(内容页),底部是页脚,我们希望点击“分类”链接时,只刷新文章列表区域。
步骤 1:修改布局页 (_Layout.cshtml)
在 @RenderBody() 的外部包裹一个 div,并给它一个唯一的 id,这个 div 将成为我们局部刷新的目标容器。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</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="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<!-- 普通链接会导致全页面刷新 -->
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<!-- AJAX 链接,点击后只刷新内容区 -->
<li>@Html.ActionLink("技术", "PostsByCategory", "Home", new { category = "tech" }, new { @class = "ajax-link" })</li>
<li>@Html.ActionLink("生活", "PostsByCategory", "Home", new { category = "life" }, new { @class = "ajax-link" })</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
<!-- 这个 div 是局部刷新的目标区域 -->
<div id="main-content">
@RenderBody()
</div>
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
<!-- 1. 引入 jQuery Unobtrusive AJAX 库 -->
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<!-- 2. 编写自定义 JavaScript 来处理 AJAX 成功后的回调 -->
<script>
$(document).ready(function () {
// 监听所有 class 为 "ajax-link" 的链接点击事件
// 注意:这里我们使用传统的 click 事件,而不是 .ajaxLink(),因为后者需要 unobtrusive-ajax 库的特殊支持
// 我们手动处理,更灵活
$(document).on("click", ".ajax-link", function (e) {
e.preventDefault(); // 阻止链接的默认跳转行为
var url = $(this).attr("href");
var $targetDiv = $("#main-content"); // 找到目标容器
// 显示加载提示(可选)
$targetDiv.html("<p>Loading...</p>");
// 使用 jQuery AJAX 发送请求
$.ajax({
url: url,
type: "GET",
success: function (result) {
// 请求成功后,将返回的 HTML 片段插入到目标 div 中
$targetDiv.html(result);
},
error: function (error) {
$targetDiv.html("<p>Error loading content.</p>");
console.log(error);
}
});
});
});
</script>
</body>
</html>
代码解释:
<div id="main-content">: 我们给@RenderBody()包裹了一个div,并设置id="main-content",这是局部刷新的“靶子”。- 导航链接: 我们为需要局部刷新的链接(如“技术”、“生活”)设置了
class="ajax-link",并指定了它们的 Action (PostsByCategory) 和参数 (category)。 jquery.unobtrusive-ajax.min.js: 这个库是 ASP.NET MVC AJAX Helper 的依赖,它可以将data-*属性自动转换为 AJAX 请求,虽然我们这里手动写了 AJAX,但引入它总没错,并且能与其他 MVC AJAX 功能兼容。- JavaScript 代码:
$(document).on("click", ".ajax-link", ...):监听所有带有ajax-link类的元素的点击事件,使用document作为父元素可以处理动态加载的内容。e.preventDefault():至关重要,阻止了浏览器默认的页面跳转行为。$.ajax({...}):发起 AJAX GET 请求。success: function(result) {...}:当服务器成功返回数据后,执行此回调函数。result就是服务器返回的 HTML 片段,我们用$targetDiv.html(result)来更新页面内容。
步骤 2:创建 Action 和 Partial View
我们需要创建一个 Action,它只返回文章列表的 HTML 片段。
Controller (HomeController.cs)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcPartialRefreshDemo.Controllers
{
public class HomeController : Controller
{
// 用于首次加载的完整页面
public ActionResult Index()
{
return View(); // 返回完整的 Index.cshtml,它会使用 _Layout.cshtml
}
// 用于 AJAX 请求的 Action,返回部分视图
public ActionResult PostsByCategory(string category)
{
// 模拟从数据库获取数据
var posts = GetPostsByCategory(category);
// 返回一个 Partial View,而不是完整的 View
// MVC 会自动寻找 ~/Views/Home/PostsByCategory.cshtml
// 并且渲染它时不会使用 _Layout.cshtml
return PartialView("_PostList", posts);
}
private List<Post> GetPostsByCategory(string category)
{
// 这里是模拟数据
var allPosts = new List<Post>
{
new Post { Title = "ASP.NET MVC 入门", Category = "tech", Content = "ASP.NET MVC 是一个强大的框架..." },
new Post { Title = "如何学习 C#", Category = "tech", Content = "C# 是一门优雅的语言..." },
new Post { Title = "我的周末生活", Category = "life", Content = "这个周末我去爬山了..." },
new Post { Title = "美食探店", Category = "life", Content = "发现了一家超好吃的拉面店..." }
};
return allPosts.Where(p => p.Category == category).ToList();
}
}
public class Post
{
public string Title { get; set; }
public string Category { get; set; }
public string Content { get; set; }
}
}
代码解释:
PostsByCategory(string category)Action 是专门为 AJAX 请求设计的。return PartialView("_PostList", posts);是关键。PartialView()方法告诉 MVC,这次渲染不要使用_Layout.cshtml布局页。"_PostList"指定了要渲染的部分视图的文件名,约定上,Partial View 的文件名以下划线_开头,以区别于常规的 View。posts是传递给 Partial View 的 Model。
Partial View (_PostList.cshtml)
这个文件非常简单,它只包含渲染文章列表所需的 HTML,没有任何布局结构。
@model IEnumerable<MvcPartialRefreshDemo.Post>
<h2>文章列表 (@Model.FirstOrDefault()?.Category)</h2>
@foreach (var post in Model)
{
<div class="post-item">
<h3>@post.Title</h3>
<p>@post.Content</p>
</div>
}
步骤 3:运行测试
- 启动项目,访问
/Home/Index,你会看到一个完整的页面,包含导航和初始的文章列表。 - 点击导航栏中的“技术”链接,你会发现,只有中间的文章列表区域(
id="main-content"发生了变化,而页头和页脚保持不动,URL 也没有改变,这就是局部刷新!
现代化方案:SPA (Single-Page Application)
对于更复杂的交互,上述方法可能会因为大量的 JavaScript 和 DOM 操作而变得难以维护,现代 Web 开发更倾向于使用 SPA 框架(如 React, Angular, Vue.js)。
SPA 的思路是:
- 首次加载:服务器只返回一个几乎为空的 HTML 页面和一个巨大的 JavaScript 包。
- 前端接管:JavaScript 框架接管整个页面的渲染。
- 数据交互:所有后续的数据请求都通过 API (通常是 RESTful API) 以 JSON 格式进行,前端拿到 JSON 数据后,再用自己的模板引擎(如 JSX, Vue Template)动态生成 HTML 并更新到页面上。
在这种模式下,MVC 的 Controller 可以专注于提供 JSON 数据(API Controller),而 View 的渲染工作几乎完全由前端框架完成,这实现了前后端更彻底的分离。
| 特性 | 传统 MVC 局部刷新 (jQuery + AJAX) | 现代化 SPA (React/Vue/Angular) |
|---|---|---|
| 核心思想 | 后端渲染 HTML 片段,前端替换 DOM | 前端渲染,后端提供 JSON 数据 API |
| 技术栈 | ASP.NET MVC, jQuery, Partial View | SPA Framework, Webpack, RESTful API |
| 优点 | 学习曲线低,适合现有 MVC 项目升级;服务器渲染利于 SEO。 | 用户体验极致流畅;前后端职责清晰,易于维护和扩展。 |
| 缺点 | 前端逻辑耦合度高,复杂应用难以维护;仍有一定服务器负载。 | 首次加载慢;SEO 需要额外处理(如 SSR);技术栈更复杂。 |
| 适用场景 | 中小型项目,有大量现有 MVC 代码,需要局部优化性能。 | 复杂的交互式 Web 应用,如后台管理系统、社交平台等。 |
对于你的问题,使用 jQuery + AJAX 配合 MVC 的 Partial View 是最直接、最符合 MVC 架构的解决方案,它完美地解决了模板页和内容页局部刷新的需求。
