159 lines
8.2 KiB
Markdown
159 lines
8.2 KiB
Markdown
# 需求文档
|
||
|
||
## 简介
|
||
|
||
Argon 主题使用 PJAX 实现无刷新页面跳转和 LazyLoad 实现图片懒加载。通过深入分析 argontheme.js(3700+ 行)的实际代码实现,发现了以下关键问题:
|
||
|
||
**PJAX 问题(2550-2700 行):**
|
||
- `pjax:complete` 和 `pjax:end` 中重复调用 `waterflowInit()` 和 `lazyloadInit()`
|
||
- `pjax:beforeReplace` 清理资源但可能遗漏某些实例
|
||
- GT4 验证码在 `pjax:end` 中重置逻辑复杂,可能状态残留
|
||
- 滚动位置恢复使用全局变量 `pjaxScrollTop`,在快速切换时可能不准确
|
||
|
||
**LazyLoad 问题(2304-2430 行):**
|
||
- `lazyloadInit()` 每次都创建新的 Observer,但清理时机依赖 PJAX 事件
|
||
- 图片加载效果使用 `setTimeout`,与浏览器渲染不同步
|
||
- 降级方案直接加载所有图片,缺少渐进式加载
|
||
- 图片状态重置(opacity、transform、transition)可能与 CSS 冲突
|
||
|
||
**性能问题:**
|
||
- 事件监听器可能重复绑定(scroll、resize 等)
|
||
- 图片预加载使用 `new Image()` 但无缓存机制
|
||
- `waterflowInit()` 在多个地方被调用,可能导致重复计算
|
||
|
||
本规范旨在优化这些功能,提升主题的稳定性和性能。
|
||
|
||
## 术语表
|
||
|
||
- **PJAX**: 一种结合 pushState 和 AJAX 的技术,实现无刷新页面跳转
|
||
- **LazyLoad**: 图片懒加载技术,延迟加载视口外的图片
|
||
- **IntersectionObserver**: 浏览器 API,用于监测元素与视口的交叉状态
|
||
- **Observer**: LazyLoad 使用的 IntersectionObserver 实例(全局变量 `lazyloadObserver`)
|
||
- **Zoomify**: 图片放大查看功能(全局数组 `zoomifyInstances`)
|
||
- **Waterflow**: 瀑布流布局
|
||
- **GT4**: 极验第四代验证码
|
||
- **Mobile_Catalog**: 移动端文章目录
|
||
- **NProgress**: 页面加载进度条库
|
||
|
||
## 需求
|
||
|
||
### 需求 1: PJAX 重复初始化消除
|
||
|
||
**用户故事:** 作为主题开发者,我希望消除 PJAX 事件中的重复初始化调用,以提升页面切换性能。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN PJAX 页面切换完成 THEN THE System SHALL 确保 `waterflowInit()` 只被调用一次
|
||
2. WHEN PJAX 页面切换完成 THEN THE System SHALL 确保 `lazyloadInit()` 只被调用一次
|
||
3. WHEN PJAX 页面切换完成 THEN THE System SHALL 确保 `zoomifyInit()` 只被调用一次
|
||
4. WHEN 分析 `pjax:complete` 和 `pjax:end` 事件处理器 THEN THE System SHALL 识别所有重复调用
|
||
5. WHEN 优化后 THEN THE System SHALL 保持功能正确性的同时减少初始化次数
|
||
|
||
### 需求 2: LazyLoad Observer 生命周期管理
|
||
|
||
**用户故事:** 作为用户,我希望图片懒加载功能在 PJAX 页面切换后能正确工作,且不会出现 Observer 泄漏。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN `lazyloadInit()` 被调用 THEN THE System SHALL 检查全局变量 `lazyloadObserver` 是否已存在
|
||
2. WHEN `lazyloadObserver` 已存在 THEN THE System SHALL 先调用 `disconnect()` 再创建新实例
|
||
3. WHEN PJAX 触发 `beforeReplace` 事件 THEN THE System SHALL 断开 Observer 并清空全局引用
|
||
4. WHEN 浏览器不支持 IntersectionObserver THEN THE System SHALL 使用滚动监听降级方案
|
||
5. WHEN Observer 清理完成 THEN THE System SHALL 确保没有内存泄漏
|
||
|
||
### 需求 3: 图片加载效果优化
|
||
|
||
**用户故事:** 作为用户,我希望图片加载时有流畅的视觉效果,不会出现闪烁或跳动。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN 图片加载完成时 THEN THE System SHALL 使用 `requestAnimationFrame` 而非 `setTimeout` 应用效果
|
||
2. WHEN 应用 fadeIn 效果时 THEN THE System SHALL 使用 CSS transition 实现平滑过渡
|
||
3. WHEN 应用 slideDown 效果时 THEN THE System SHALL 使用 CSS transform 实现硬件加速
|
||
4. WHEN 图片加载失败时 THEN THE System SHALL 显示原始 src 并停止重试
|
||
5. WHEN 清理图片状态时 THEN THE System SHALL 移除所有 `lazyload-style-*` 类名
|
||
|
||
### 需求 4: GT4 验证码状态管理优化
|
||
|
||
**用户故事:** 作为用户,我希望在 PJAX 页面切换后验证码能正确重置和重新初始化。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN PJAX 触发 `end` 事件且页面包含 `#geetest-captcha` THEN THE System SHALL 重置验证码状态变量
|
||
2. WHEN 重置验证码状态 THEN THE System SHALL 清空所有隐藏字段(lot_number、captcha_output、pass_token、gen_time)
|
||
3. WHEN 重置验证码状态 THEN THE System SHALL 清空验证码容器 DOM
|
||
4. WHEN 验证码容器清空后 THEN THE System SHALL 调用初始化函数重新加载验证码
|
||
5. WHEN 验证码初始化失败 THEN THE System SHALL 记录警告但不影响页面其他功能
|
||
|
||
### 需求 5: 滚动位置管理优化
|
||
|
||
**用户故事:** 作为用户,我希望在 PJAX 页面切换时滚动位置能正确恢复或重置。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN PJAX 开始加载新页面 THEN THE System SHALL 根据链接类型决定是否记录滚动位置
|
||
2. WHEN 用户点击分页链接 THEN THE System SHALL 记录目标滚动位置到全局变量 `pjaxScrollTop`
|
||
3. WHEN PJAX 完成页面切换 THEN THE System SHALL 根据 `pjaxScrollTop` 值恢复滚动位置
|
||
4. WHEN 滚动位置恢复后 THEN THE System SHALL 重置 `pjaxScrollTop` 为 0
|
||
5. WHEN Banner 设置为封面模式 THEN THE System SHALL 根据页面类型调整滚动位置计算逻辑
|
||
|
||
### 需求 6: Zoomify 实例清理优化
|
||
|
||
**用户故事:** 作为主题开发者,我希望在 PJAX 页面切换时完整清理 Zoomify 实例,避免内存泄漏。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN PJAX 触发 `beforeReplace` 事件 THEN THE System SHALL 遍历全局数组 `zoomifyInstances`
|
||
2. WHEN 遍历 Zoomify 实例 THEN THE System SHALL 检查实例是否存在 `destroy` 方法
|
||
3. WHEN 实例存在 `destroy` 方法 THEN THE System SHALL 调用该方法销毁实例
|
||
4. WHEN 所有实例销毁完成 THEN THE System SHALL 清空 `zoomifyInstances` 数组
|
||
5. WHEN 清理完成 THEN THE System SHALL 移除所有 `.zoomify-initialized` 类名
|
||
|
||
### 需求 7: Tippy 实例清理优化
|
||
|
||
**用户故事:** 作为主题开发者,我希望在 PJAX 页面切换时清理 Tippy 提示框实例,避免残留。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN PJAX 触发 `beforeReplace` 事件 THEN THE System SHALL 检查 `tippy` 是否已定义
|
||
2. WHEN `tippy` 已定义 THEN THE System SHALL 查找所有 `[data-tippy-root]` 元素
|
||
3. WHEN 找到 Tippy 元素 THEN THE System SHALL 调用元素的 `_tippy.destroy()` 方法
|
||
4. WHEN 销毁完成 THEN THE System SHALL 移除所有 `.tippy-initialized` 类名
|
||
5. WHEN 销毁过程出错 THEN THE System SHALL 捕获异常并继续处理其他实例
|
||
|
||
### 需求 8: 移动端目录初始化修复
|
||
|
||
**用户故事:** 作为移动端用户,我希望在 PJAX 页面切换后文章目录能正确显示和工作。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN PJAX 触发 `end` 事件 THEN THE System SHALL 检查 `window.resetMobileCatalog` 函数是否存在
|
||
2. WHEN 函数存在 THEN THE System SHALL 在 100ms 延迟后调用该函数
|
||
3. WHEN 重置目录状态 THEN THE System SHALL 清理旧目录相关 DOM 和事件
|
||
4. WHEN 页面需要目录 THEN THE System SHALL 重新初始化移动端目录
|
||
5. WHEN 页面不需要目录 THEN THE System SHALL 确保目录相关元素被隐藏或移除
|
||
|
||
### 需求 9: 事件监听器防重复绑定
|
||
|
||
**用户故事:** 作为主题开发者,我希望事件监听器能正确管理,避免内存泄漏和重复绑定。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN 绑定滚动事件监听器时 THEN THE System SHALL 使用命名函数而非匿名函数
|
||
2. WHEN PJAX 清理资源时 THEN THE System SHALL 移除所有已绑定的事件监听器
|
||
3. WHEN 重新初始化功能时 THEN THE System SHALL 检查事件监听器是否已存在
|
||
4. WHEN 使用事件委托时 THEN THE System SHALL 在父元素上绑定而非每个子元素
|
||
5. WHEN 页面卸载时 THEN THE System SHALL 清理所有残留的事件监听器
|
||
|
||
### 需求 10: 图片预加载缓存机制
|
||
|
||
**用户故事:** 作为用户,我希望图片预加载能使用浏览器缓存,避免重复加载。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN `loadImage()` 函数创建临时 Image 对象 THEN THE System SHALL 检查浏览器缓存
|
||
2. WHEN 图片已在缓存中 THEN THE System SHALL 直接使用缓存而非重新下载
|
||
3. WHEN 图片加载完成 THEN THE System SHALL 确保浏览器已缓存该图片
|
||
4. WHEN 图片加载失败 THEN THE System SHALL 不进行重试以避免浪费带宽
|
||
5. WHEN 使用预加载 THEN THE System SHALL 利用浏览器原生缓存机制而非自建缓存
|