Vue 2.0多页面应用模板:从SPA困境到工程化落地
简介这是一套基于 Vue 2.0 打造的多页面应用模板面向需要在同一工程下管理多个独立页面的前端开发者有助于避开单页应用在入口扩展、独立构建与路由耦合上的常见问题。压缩包共 32 个文件整体仅 31KB核心由 15 个 JavaScript 配置与构建脚本、6 个 Vue 页面/组件构成并辅以 HTML 入口、ESLint、Babel、editorconfig 等工程化配置完整覆盖开发调试、生产打包、环境变量与代码规范等环节。目录按 src/module、components、assets 分层组织可以清晰看出模块划分与可复用组件的位置便于直接在其上扩展业务功能。目前已有 4660 人学习下载。借助这套模板既能省去手动搭建 webpack 多页配置的繁琐步骤也能通过阅读源码理解非 vue-cli 场景下的构建思路适合团队作为前端多页项目的初始骨架。1. Vue 2.0 多页面应用模板为什么 SPA 不是唯一解接到一个需要 SEO 的官网或者一个后台系统里登录、报表、配置三个模块要独立部署时再拿 Vue 2.0 默认的 SPA 单页模板硬扛就会陷入两难首屏要等一整包 JS 下载完才能渲染搜索引擎抓到的只有一个空壳。Vue 2.0准确说是 Vue 2.x多页面应用模板解决的正是这个场景——它把 webpack 的多入口、多 HTML 页面、公共依赖抽离都封装好让你基于 Vue 2 生态一套代码管理多个独立页面。模板本身不神秘就是约定好目录结构配置好每个页面的入口和构建产物。适合正在维护 Vue 2 存量项目的团队也适合新手想快速理解多页应用工程化怎么写。多页面不是倒退而是 SPA 覆盖不了 SEO 和独立部署诉求时的务实选择。2. 多页面模板的原理边界MPA 和 SPA 怎么选脚手架版本怎么定2.1 多页面应用的核心机制多入口、多 Document、独立加载SPA 的构建产物通常是一个 index.html 加一堆 JS/CSS浏览器首次只加载一个 Document之后靠路由切换视图。MPA 则完全不同每个页面都有独立的 HTML 文件、独立的入口 JS浏览器访问 /list.html 时加载的是 list 页面自己的 Document 和资源。这是两者最本质的区别也决定了不同的优化路径。对比维度SPAVue 默认模板MPA本文模板页面载体单个 index.html每个页面一个 HTML路由方式vue-router 前端路由浏览器原生导航SEO 友好度低首屏内容靠 JS 渲染高每个 HTML 可独立被抓取构建配置单入口多 entry 多 HtmlWebpackPlugin首屏加载受整个应用体积影响只加载当前页面依赖公共代码天然共享需要主动抽离判断标准我一般看三点有没有 SEO 需求、模块之间是否需要独立部署、团队是否希望“改一个页面不动其他页面”。三条里命中两条多页面模板就是更好的选择。2.2 vue-cli 2 与 vue-cli 3/4 的模板差异先分清你的脚手架版本“多页面应用模板”这个标题背后其实是两套完全不同的实现路径。vue-cli 2 时代项目结构是 build/webpack.base.conf.js 手动配置 entry 和 HtmlWebpackPluginvue-cli 3 以后引入了 vue.config.js 的 pages 配置原生支持多页面。这个差异直接决定了模板长什么样动手前先确认自己的脚手架版本。对比项vue-cli 2webpack 3vue-cli 3 / 4webpack 4配置文件build/webpack.base.conf.jsvue.config.js多页面写法手写 entry 对象 new HtmlWebpackPluginpages 对象声明式配置维护成本中改动 webpack 配置容易踩坑低模板 API 收敛升级难度迁移到 vue-cli 3 需重写配置原生支持无需额外插件模板的价值在 vue-cli 2 时代尤其明显每个页面都要手动 new 一个 HtmlWebpackPluginchunks 顺序错了就白屏这些重复劳动被封装成模板后新增页面只需要复制一个目录再改两行配置。2.3 目录结构怎么排约定优于配置的 pages 组织方式模板的核心是目录约定。我常用的结构是把每个页面收拢到 src/pages 下独立成文件夹页面自己的组件、路由、状态都放在这个目录里避免跨页面互相引用导致构建产物分不开。src/ ├── pages/ │ ├── index/ │ │ ├── main.js # 页面入口必须存在 │ │ ├── App.vue │ │ └── index.html # 页面模板HtmlWebpackPlugin 使用 │ └── list/ │ ├── main.js │ ├── App.vue │ └── index.html ├── common/ # 跨页面的公共组件、工具函数 │ └── utils.js └── styles/ └── common.scss # 公共样式由各入口 import这个结构的约束很简单每个页面目录自包含公共代码统一放 src 下而不是页面目录里。这样新增一个页面时复制目录、改 pages 配置、重启开发服务器三步就能跑起来。公共逻辑如果放错了位置后面分包和避坑那几章就会频繁碰到问题。3. 跑通最小多页面模板vue-cli 3/4 的 pages 配置与目录组织3.1 最小可复现步骤初始化项目到第一个双页面先创建一个基础的 Vue 2 项目再改造成多页面。命令如下vue create my-mpa-template # 选择 Vue 2 preset不需要额外的 TS 和 Router 选项 cd my-mpa-template创建完成后删除 src 下的默认单页结构建立 pages 目录。把原来的 App.vue 和 main.js 复制成两份分别放到 pages/index 和 pages/list 下mkdir -p src/pages/index src/pages/list cp src/App.vue src/pages/index/App.vue cp src/App.vue src/pages/list/App.vue # 分别改写两个 main.js指向各自的 App.vue两个 main.js 的内容几乎一样只是引入路径要保持相对正确。这种刻意重复的好处是页面之间彻底解耦你可以放心地在 index 页面引入一个重量级图表库而 list 页面完全不受影响。如果你希望公共逻辑共享放在 src/common 里让各页面 import 即可而不是直接改对方的目录。3.2 vue.config.js 的 pages 完整配置与参数说明这是整个模板的核心配置。vue-cli 3/4 会在构建时读取 pages 对象自动为每个页面创建入口和 HtmlWebpackPlugin 实例const path require(path) module.exports { publicPath: process.env.NODE_ENV production ? /dist/ : /, pages: { index: { entry: src/pages/index/main.js, template: src/pages/index/index.html, filename: index.html, title: 首页, chunks: [chunk-vendors, chunk-common, index] }, list: { entry: src/pages/list/main.js, template: src/pages/list/index.html, filename: list.html, title: 列表页, chunks: [chunk-vendors, chunk-common, list] } }, devServer: { port: 8080 } }pages 配置里每个字段都有明确的用途entry 是页面入口 JS决定了该页面会打包哪些依赖template 是 HTML 模板文件构建时会把 JS/CSS 注入到这个文件里filename 是最终生成的文件名浏览器直接访问的就是它title 会覆盖模板里的title标签chunks 则声明该页面加载哪些 chunk。chunks 这里我习惯写全避免页面多了之后公共 chunk 顺序错乱的问题后面避坑章节会专门讲。参数调整的经验title 字段适合静态页标题如果页面标题需要根据查询参数动态变化就要在页面代码里用 document.title 覆盖。filename 建议用英文小写避免部署在 Nginx 等服务器上由大小写引发的 404。3.3 开发代理、publicPath 与 favicon模板里的隐性配置多页面模板接入真实后端接口时开发环境要配置代理。devServer.proxy 和单页应用没有区别但注意多页面场景下每个页面都会发起跨域请求代理配置集中管理更省心devServer: { proxy: { /api: { target: http://api.example.com, changeOrigin: true, pathRewrite: { ^/api: } } } }publicPath 是另一个容易忽略的字段。它控制构建产物里 JS/CSS 的引用路径。生产环境部署到域名子目录时publicPath 要设置为/your-sub-path/如果部署在站点根目录则用/如果产物需要放在一个未知路径下用相对路径./最稳妥。这里没有统一的正确答案只跟着部署方式走。favicon 的坑比较隐蔽vue-cli 默认只处理 public 目录下的 favicon.ico多页面模板里如果每个页面模板都写死link relicon href/favicon.ico开发环境没问题生产构建后路径就可能失效。我用一个简单做法把 favicon 放在 public 下模板里用% BASE_URL %favicon.ico引用BASE_URL 会自动适配 publicPath。4. 上线前的多页面工程化分包、标题注入与路由取舍4.1 公共依赖抽离splitChunks 在 MPA 里的正确姿势多页面模板运行一段时间后你会发现问题每个页面的 bundle 里都打了一份 Vue 核心库体积急剧膨胀。默认配置下 vue-cli 只把 node_modules 里的依赖抽成 chunk-vendors但如果两个页面依赖同一个公共工具函数它就会被重复打包。这时候需要在 vue.config.js 里自定义 splitChunksmodule.exports { chainWebpack: config { config.optimization.splitChunks({ chunks: all, cacheGroups: { vueCore: { name: chunk-vendors, test: /[\\/]node_modules[\\/](vue|vue-router|vuex|axios)[\\/]/, priority: 10, chunks: all }, commonLib: { name: chunk-common, test: path.resolve(__dirname, src/common), priority: 5, minChunks: 2, chunks: all } } }) } }这段配置把 vue、vue-router 这类框架依赖固定抽成 chunk-vendors把 src/common 下被至少两个页面引用的模块抽成 chunk-common。参数说明test 是模块匹配规则priority 决定分组优先级数值大的先匹配minChunks 表示最少被几个 chunk 引用才抽离。注意 pages 配置里 chunks 数组要包含这两个名字否则页面不会加载它们。一个常见的误用是把所有 node_modules 依赖都打进 chunk-vendors导致首屏要下载一个极大的 vendor 包。正确的做法是只把真正跨页面共享的框架依赖放进去其余按页面各自打包。4.2 每个页面的标题和 Meta 怎么动态控制pages 配置里的 title 只能搞静态标题页面内部的动态标题要靠代码覆盖。我习惯写一个小工具函数放在 src/common 里每个页面 main.js 初始化时调用// src/common/usePageMeta.js export function setPageMeta(title, description) { document.title title let meta document.querySelector(meta[namedescription]) if (!meta) { meta document.createElement(meta) meta.name description document.head.appendChild(meta) } meta.content description || } // 页面内使用 import { setPageMeta } from /common/usePageMeta setPageMeta(商品列表 - 第 2 页, 按分类浏览全部商品信息)这个函数在 mounted 或路由守卫里调用均可。注意多页面场景下 document.title 的覆盖是瞬时的如果页面有异步数据建议在数据拿到后再调用一次避免标题闪烁。HTML 模板里也可以注入占位变量但动态场景用代码覆盖更灵活。4.3 按页面路由组织组件MPA 场景下还要不要 vue-router很多人问多页面模板里还能用 vue-router 吗答案是可以但要分清粒度。页面级别的跳转走 href 或 window.location浏览器原生导航页面内部的局部视图切换比如一个 tab 面板用 vue-router 的 hash 模式是没有问题的。场景推荐方案理由页面间跳转a href/list.html符合 MPA 语义可被搜索引擎索引页面内 tab 切换组件 v-if 控制无需引入路由页面内复杂子视图vue-router hash 模式保留浏览器前进后退需要强调的是不要在 MPA 的页面里使用 vue-router 的 history 模式。因为每个页面是独立的 HTMLhistory 模式的地址会绕过服务器实际文件刷新时直接 404。5. 多页面模板避坑状态百出先查这五个高频问题5.1 坑一页面 A 的 JS 跑到了页面 B 上现象打开 list.html 时页面执行了 index 页面的初始化逻辑弹窗、事件绑定都在 B 页面出现。原因HtmlWebpackPlugin 的 chunks 没有显式指定webpack 自动注入时把所有 entry 的 chunk 都塞进了每个 HTML。解决在 pages 配置里给每个页面写全 chunks 数组明确只加载自己的业务 chunk 和公共 chunk。排查手段是打开构建后的 HTML 文件看 script 标签如果出现两个页面的业务 chunk就是这个原因。5.2 坑二打包后资源全部 404现象本地 npm run serve 一切正常build 完上传到服务器后页面白屏控制台全是资源加载失败。原因publicPath 配置和生产部署路径不一致。构建生成的引用路径如果是/js/index.js而项目部署在/sub/子目录下就必然 404。解决确认部署路径后设置 publicPath子目录部署用/sub/不确定路径时用相对路径./。注意相对路径会影响路由懒加载的加载基址多页面场景下页面级资源没问题但页面内异步组件要配合 webpack 的publicPath处理。5.3 坑三公共样式重复打进每个页面包现象一个 20KB 的公共样式文件在三个页面的产物里各出现一次构建体积虚高。原因样式文件被多个入口直接 import且 splitChunks 配置没有覆盖样式模块。解决把公共样式放在 src/styles/common.scss在 pages 配置中让每个页面 entry 都 import 它同时给 splitChunks 增加 CSS 分组或者依赖 vue-cli 的 css.extract 配置。验证方式检查 dist/css 下是否只有一个公共样式 chunk而不是每个页面目录里各有一份。5.4 坑四开发环境新增页面后刷新 404现象在 pages 配置里加了一个新页面npm run serve 状态下直接访问新页面地址提示 404重启后又正常。原因devServer 的 historyApiFallback 默认只处理单入口新增 HTML 文件不会热生效。解决重启开发服务器让 webpack 重新编译入口。如果频繁新增页面嫌重启麻烦可以配置 devServer.historyApiFallback 的 rewrites 规则把未匹配路径指到对应模板。但注意 rewrites 要在模板文件生成后才有效。5.5 坑五vue-cli 2 老项目改造时 HtmlWebpackPlugin 重复实例现象老项目从单页改多页后构建报错或者页面加载顺序错乱chunk-vendors 没被正确引用。原因vue-cli 2 的 webpack.base.conf.js 原本只有一个 HtmlWebpackPlugin 实例多页需要遍历 pages 数组动态创建且 plugin 的 chunks 顺序必须把 vendor 放在最前。解决写一个遍历函数生成 entries 和 pluginschunks 第一项固定为 vendor再放公共 chunk 和页面 chunkpages.forEach(page { webpackConfig.plugins.push(new HtmlWebpackPlugin({ filename: page.filename, template: page.template, chunks: [manifest, vendor, common, page.name] })) })这段配置里的 manifest 保存 webpack 运行时vendor 是公共依赖common 是业务公共代码顺序不能乱。老项目迁移到 vue-cli 3/4 是更省心的方案如果暂时不能迁移上述写法能帮你撑一阵。6. 顺着模板做验证构建产物检查与新项目选型判断6.1 构建产物里重点检查三个文件模板搭好后光跑通还不够我用这三个检查项判断模板是否健康# 1. 检查每个 HTML 引用的 JS 是否只包含自己的 chunk grep -o src[^]* dist/list.html # 2. 检查公共 chunk 是否只有一个 ls dist/js/ # 3. 检查首屏体积大于 200KB 要警惕 du -sh dist/js/*正常的多页面产物应该是每个页面 HTML 引用了 chunk-vendors chunk-common 自己的页面 chunk公共 chunk 只有一个每个页面 chunk 体积相对可控。我正在接手的某项目模板就是通过第 2 条查到有五个重复的公共 chunk排查出 splitChunks 配置失效。这套检查能省很多线上排错时间。6.2 要不要从 Vue 2 模板升级到 Vue 3 多页每次新建项目团队都会纠结这个问题。如果维护的是 Vue 2 存量系统组件库依赖 Vue 2 生态升级意味着重写大量业务代码此时这套多页面模板依然能稳定服务。如果是全新项目建议直接考虑 Vue 3 Vite 多页配置原理是相通的多入口、共享依赖抽离、每个页面独立 HTML。从我自己的操作习惯看模板的构建配置部分不变变的是入口文件的写法和构建工具的速度。每接到 SEO 或独立部署需求我都会先翻出这套模板改目录结构直接落地省掉重复写 webpack 入口的功夫把精力留给页面本身。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

CFCA精品可可认证:证书背后的校友网络才是进阶捷径

CFCA精品可可认证:证书背后的校友网络才是进阶捷径

说实话,一提到精品可可这行,很多人第一反应是“考个证给自己镀层金”。但我在这个圈子里泡了几年,越来越觉得证书本身只能算敲门砖,真正让你少走三年弯路、摸到行业底层逻辑的,反而是证书背后的那张关系网。这就是我跟…

2026/10/14 20:35:54 阅读更多 →
嵌入式C++开发核心注意事项:内存、中断与可移植性实战总结

嵌入式C++开发核心注意事项:内存、中断与可移植性实战总结

做嵌入式C开发这几年,我最深的体会是:很多人其实不是不会写C,而是把C那一套“顺手的习惯”直接搬进了单片机,结果踩了一地的坑。桌面端的析构函数、动态容器、异常抛出,在动辄只有几十到几百KB RAM的MCU上完全是另一个…

2026/10/14 20:35:54 阅读更多 →
Lua 脚本

Lua 脚本

官方文档:https://redis.io/docs/latest/develop/programmability/lua-api EVAL script numkeys key [key …] arg [arg …] script:lua脚本numkeys:涉及多少个key值key [key ...]:lua脚本所需访问的keyarg [arg ...]&#xff1…

2026/10/14 20:35:54 阅读更多 →

最新新闻

SpringBoot+Vue轻量级博客系统设计与实现

SpringBoot+Vue轻量级博客系统设计与实现

1. 项目概述:SpringBootVue轻量级博客系统设计去年帮学弟评审毕业设计时,发现市面上很多博客系统要么功能冗余,要么扩展性差。于是我们决定用SpringBootVue搭建一个轻量级但五脏俱全的在线创作社区。这个系统最核心的特点是采用前后端分离架构…

2026/10/15 6:55:51 阅读更多 →
正念与心流:10分钟呼吸练习,让专注成为生命底色

正念与心流:10分钟呼吸练习,让专注成为生命底色

1. 先说清楚:我们到底在谈什么你有没有过这样的时刻:明明手头有一件重要的事要做,却忍不住五分钟刷一次手机;开会时脑子飘到晚上吃什么;想读几页书,眼睛盯着一行字,心里却已经把明天的待办事项过…

2026/10/15 6:55:51 阅读更多 →
Oracle 数据实时入仓 Doris 和 StarRocks 怎么做?CDC、全量迁移与 5 种方案对比

Oracle 数据实时入仓 Doris 和 StarRocks 怎么做?CDC、全量迁移与 5 种方案对比

在很多企业系统中,Oracle 负责在线事务处理,Doris 或 StarRocks 负责报表、数据分析和实时数据服务。当订单、用户、支付和日志数据持续增长时,直接在 Oracle 上运行复杂统计 SQL,可能影响线上业务。因此,很多团队会建…

2026/10/15 6:55:51 阅读更多 →
SpringBoot+Vue+MyBatis构建企业级电商平台实战

SpringBoot+Vue+MyBatis构建企业级电商平台实战

1. 项目概述"企业级网购平台管理系统"是一个基于SpringBootVueMyBatis技术栈的完整电商解决方案。这套源码包含了电商平台的核心功能模块,采用前后端分离架构设计,数据库使用MySQL,适合快速构建中小型B2C或B2B电商平台。我在实际电…

2026/10/15 6:55:51 阅读更多 →
聚簇索引vs非聚簇索引:从底层原理到实战避坑全解析

聚簇索引vs非聚簇索引:从底层原理到实战避坑全解析

做后端开发这几年,索引相关的坑我踩过不少。面试被问过无数次“聚簇索引和非聚簇索引区别”,带新人的时候也发现,大部分同学对这两个词的理解停留在“一个有序一个无序”或者“聚簇索引就是主键”这种模糊层面。一旦落到实际业务,…

2026/10/15 6:55:51 阅读更多 →
盲盒商城软件开发案例:连接概率说明、微信支付、在线开赏与积分兑换

盲盒商城软件开发案例:连接概率说明、微信支付、在线开赏与积分兑换

盲盒商城的购买过程与普通商品商城有所不同。用户在付款前,需要了解盲盒价格、可抽取内容和相关规则;完成支付后,再进入开赏环节。商品展示、概率说明、支付结果和积分记录之间,需要形成清晰的操作顺序。 某公司的这套盲盒商城软件…

2026/10/15 6:54:51 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →