首页
/ Bilibili-Evolved状态持久化引擎:从数据存储到自定义扩展全解析

Bilibili-Evolved状态持久化引擎:从数据存储到自定义扩展全解析

2026-02-05 04:09:36作者:魏献源Searcher

Bilibili-Evolved作为强大的哔哩哔哩增强脚本,其状态持久化中间件负责管理用户配置、组件状态等关键数据的存储与恢复。该引擎基于GM API(Greasemonkey API)构建核心存储能力,并通过模块化设计支持自定义扩展,确保用户设置在页面刷新或浏览器重启后依然保持一致。本文将深入解析其实现原理、核心模块及扩展方式。

存储引擎架构概览

状态持久化系统采用分层设计,核心模块位于src/core/settings/目录,包含数据读写、监听机制和代理封装三个主要层次:

  • 数据层:通过read.tswrite.ts实现GM API的封装与数据处理
  • 代理层:使用proxy.ts创建响应式设置对象,支持属性访问拦截
  • 监听层:通过listener.ts提供设置变更的订阅机制

存储引擎架构

设置面板界面:用户通过settings-panel/组件配置存储的各项参数

核心实现:GM API封装与数据处理

数据读取流程

read.ts实现了从GM存储读取数据并与默认值合并的核心逻辑:

export const mergeValue = (gmValue: any, currentValue: any) => {
  if (typeof gmValue === 'object') {
    return lodash.defaultsDeep(gmValue, currentValue)
  }
  return gmValue
}

export const readSettings = (obj: any) => {
  for (const [key, value] of Object.entries(obj)) {
    const gmValue = GM_getValue(key, value)
    obj[key] = mergeValue(gmValue, value)
  }
  return obj
}

该实现通过defaultsDeep确保复杂对象的深度合并,解决了GM API原生不支持嵌套对象合并的问题。初始化时,index.ts调用readSettings加载并合并数据:

state.internalSettings = createProxy(readSettings(state.internalSettings), settingsChangedHandler)

响应式代理机制

proxy.ts创建的代理对象是实现响应式的关键,当设置值被修改时会自动触发存储和通知:

export const createProxy = (target: any, onChange: (path: string, value: any, oldValue: any) => void) => {
  return new Proxy(target, {
    set(target, prop, value) {
      const oldValue = target[prop]
      target[prop] = value
      onChange(prop.toString(), value, oldValue)
      return true
    },
    // 嵌套对象代理逻辑...
  })
}

高级特性:设置监听与组件集成

系统提供两种监听机制,满足不同层级的设置变更需求:

基础设置监听

通过addSettingsChangeListener实现对任意设置路径的监听:

export const addSettingsChangeListener = <T = any>(
  path: string,
  listener: ValueChangeListener<T>,
  initCall = false,
) => {
  const handlers = registeredListeners.get(path)
  if (handlers) {
    handlers.push(listener)
  } else {
    registeredListeners.set(path, [listener])
  }
  // 初始化调用逻辑...
}

组件专用监听

针对组件设置的特殊路径格式,提供addComponentListener简化监听注册:

export const addComponentListener = <T = any>(
  path: string,
  listener: ValueChangeListener<T>,
  initCall = false,
) => {
  addSettingsChangeListener(componentPath(path), listener, initCall)
}

组件路径转换逻辑会自动将component.option格式的路径转换为内部存储键:

const componentPath = (path: string) => {
  const [name, ...optionPath] = path.split('.')
  // 内置组件与用户组件路径转换...
  return `components.${name}.options.${optionName}`
}

自定义扩展:构建第三方存储引擎

虽然当前实现基于GM API,但架构设计预留了扩展点,可通过以下方式实现自定义存储引擎:

  1. 抽象存储接口:定义统一的StorageEngine接口,包含get/set/remove等方法
  2. 实现引擎适配器:为不同存储后端(如IndexedDB、localStorage)编写适配器
  3. 注册引擎实例:通过设置面板的外部操作模块切换存储引擎

存储引擎扩展点

管理面板中的高级设置区域:可扩展存储引擎配置界面

性能优化与最佳实践

数据合并策略

mergeValue函数采用深度合并而非完全覆盖,确保配置升级时保留用户原有设置:

export const mergeValue = (gmValue: any, currentValue: any) => {
  if (typeof gmValue === 'object') {
    return lodash.defaultsDeep(gmValue, currentValue)
  }
  return gmValue
}

批量操作建议

对于多设置项修改,建议使用事务模式减少GM API调用次数,可参考initInternalSettings中的批量初始化逻辑。

总结与扩展方向

Bilibili-Evolved的状态持久化引擎通过GM API封装、响应式代理和事件监听三大机制,实现了高效可靠的设置管理。未来可扩展的方向包括:

完整实现可参考官方文档features.md中的"高级存储"章节,或通过bisect工具调试存储相关问题。

登录后查看全文
热门项目推荐
相关项目推荐