You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET MVC动态切换主题:如何避免布局重载仅渲染主体

无刷新主题切换实现方案(仅更新Body区域)

现有问题分析

当前方案通过ViewBag判断主题并渲染不同CSS和导航,但依赖location.reload()全页刷新,且ViewBag仅单次请求有效,无法持久化主题状态。以下是优化后的无刷新实现步骤:


1. 持久化主题状态

将主题状态存储到Session中(或Cookie),确保跨请求保留,同时修改控制器方法返回主题标识:

// 配置Session服务(Startup.cs/Program.cs)
// 在ConfigureServices中添加
services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromDays(7);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// 在Configure中启用(需放在UseRouting之后,UseEndpoints之前)
app.UseSession();
// HomeController.cs
[HttpGet]
public IActionResult ToDark()
{
    HttpContext.Session.SetInt32("Theme", 1);
    return Json(new { Theme = 1 });
}

[HttpGet]
public IActionResult ToLight()
{
    HttpContext.Session.SetInt32("Theme", 0);
    return Json(new { Theme = 0 });
}

2. 改造Layout,支持前端动态切换

移除服务器端条件渲染导航的逻辑,改为动态修改CSS类和按钮文本,同时给主题CSS添加ID方便切换:

<!-- Shared/_Layout.cshtml - head区域 -->
<link id="theme-css" rel="stylesheet" href="@(HttpContext.Session.GetInt32("Theme") == 1 ? "~/css/dark-theme.css" : "~/lib/bootstrap/dist/css/bootstrap.min.css")" />

<!-- Shared/_Layout.cshtml - 导航区域 -->
<nav id="main-nav" class="navbar navbar-expand-lg @(HttpContext.Session.GetInt32("Theme") == 1 ? "bg-dark" : "navbar-light bg-white border-bottom box-shadow mb-3")" 
     data-bs-theme="@(HttpContext.Session.GetInt32("Theme") == 1 ? "dark" : "light")">
    <div class="container-fluid">
        <!-- 原有导航内容 -->
    </div>
    <div class="d-flex form-check form-switch justify-content-end mx-lg-3">
        <input id="theme-toggle" class="btn" type="button" onclick="toggleTheme()" 
               value="@(HttpContext.Session.GetInt32("Theme") == 1 ? "Light" : "Dark")">
    </div>
</nav>

<!-- Shared/_Layout.cshtml - Body内容容器 -->
<div class="main-content">
    @RenderBody()
</div>

3. 提取Body内容为局部视图

将原视图的内容提取到局部视图Views/Shared/_MainContent.cshtml,并在主视图中引用:

<!-- 主视图(如Index.cshtml) -->
@await Html.PartialAsync("_MainContent")

添加控制器方法返回该局部视图:

// HomeController.cs
public IActionResult GetMainContent()
{
    // 若需传递模型,此处传入对应模型对象
    return PartialView("_MainContent");
}

4. 前端JS实现无刷新切换

替换原有刷新页面的逻辑,改为请求服务器更新主题状态后,动态修改CSS、导航样式,并重新加载Body局部视图:

function toggleTheme() {
    const toggleBtn = document.getElementById('theme-toggle');
    const targetTheme = toggleBtn.value === 'Dark' ? 1 : 0;
    const apiUrl = targetTheme === 1 ? '@Url.Action("ToDark", "Home")' : '@Url.Action("ToLight", "Home")';

    $.get(apiUrl, function(res) {
        const cssLink = document.getElementById('theme-css');
        const mainNav = document.getElementById('main-nav');

        if (res.Theme === 1) {
            // 切换为深色主题
            cssLink.href = '@Url.Content("~/css/dark-theme.css")';
            mainNav.className = 'navbar navbar-expand-lg bg-dark';
            mainNav.setAttribute('data-bs-theme', 'dark');
            toggleBtn.value = 'Light';
        } else {
            // 切换为浅色主题
            cssLink.href = '@Url.Content("~/lib/bootstrap/dist/css/bootstrap.min.css")';
            mainNav.className = 'navbar navbar-expand-lg navbar-light bg-white border-bottom box-shadow mb-3';
            mainNav.setAttribute('data-bs-theme', 'light');
            toggleBtn.value = 'Dark';
        }

        // 重新加载Body内容(同步主题样式)
        $.get('@Url.Action("GetMainContent", "Home")', function(content) {
            $('.main-content').html(content);
        });
    });
}

5. 页面初始化主题状态

在Layout中添加初始化脚本,确保页面加载时主题样式正确:

$(function() {
    const currentTheme = '@HttpContext.Session.GetInt32("Theme")';
    const cssLink = document.getElementById('theme-css');
    const mainNav = document.getElementById('main-nav');
    const toggleBtn = document.getElementById('theme-toggle');

    if (currentTheme === '1') {
        cssLink.href = '@Url.Content("~/css/dark-theme.css")';
        mainNav.className = 'navbar navbar-expand-lg bg-dark';
        mainNav.setAttribute('data-bs-theme', 'dark');
        toggleBtn.value = 'Light';
    } else {
        cssLink.href = '@Url.Content("~/lib/bootstrap/dist/css/bootstrap.min.css")';
        mainNav.className = 'navbar navbar-expand-lg navbar-light bg-white border-bottom box-shadow mb-3';
        mainNav.setAttribute('data-bs-theme', 'light');
        toggleBtn.value = 'Dark';
    }
});

内容的提问来源于stack exchange,提问作者Musa AKYUZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:05:06