开发指南
本章节为开发者提供完整的 Obsidian 扩展开发指南,帮助你创建自定义插件和主题。
为什么要开发?
| 场景 | 说明 |
|---|---|
| 自定义功能 | 现有插件不满足需求 |
| 工作流自动化 | 优化个人工作流程 |
| 分享贡献 | 贡献社区,帮助他人 |
| 学习成长 | 提升 TypeScript/CSS 技能 |
快速开始
环境准备
必需工具:
- Node.js 18+
- npm 或 pnpm
- Git
- VS Code(推荐)
推荐扩展:
- TypeScript
- ESLint
- Prettier
创建第一个插件
bash
# 1. 创建插件目录
mkdir my-plugin
cd my-plugin
# 2. 初始化项目
npm init -y
# 3. 安装依赖
npm install obsidian @types/node typescript
# 4. 创建基本文件
mkdir src
touch src/main.ts manifest.json styles.css最小插件示例
typescript
// src/main.ts
import { Plugin } from 'obsidian';
export default class MyPlugin extends Plugin {
async onload() {
this.addCommand({
id: 'hello-world',
name: 'Say Hello',
callback: () => {
console.log('Hello, Obsidian!');
}
});
}
}json
// manifest.json
{
"id": "my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"minAppVersion": "0.15.0",
"description": "My first Obsidian plugin",
"author": "Your Name",
"authorUrl": "https://example.com",
"isDesktopOnly": false
}内容导航
入门教程
| 主题 | 说明 | 进入 |
|---|---|---|
| 开发入门 | 环境配置与基础概念 | 新手必读 |
| 插件开发教程 | 手把手开发完整插件 | 循序渐进 |
| API 参考 | Obsidian API 完整参考 | 速查手册 |
进阶开发
| 主题 | 说明 | 进入 |
|---|---|---|
| 插件开发详解 | 命令、视图、设置系统 | 深入理解 |
| 主题开发 | CSS 主题与样式定制 | 视觉定制 |
| 调试技巧 | 开发者工具与常见问题 | 问题排查 |
发布与分享
| 主题 | 说明 | 进入 |
|---|---|---|
| 发布插件 | 提交到社区插件市场 | 分享成果 |
| 示例项目 | 优秀开源项目分析 | 学习参考 |
| 常见问题 | 开发中常见问题解答 | 问题解决 |
开发资源
官方资源
文档:
社区:
- Discord: #plugin-dev 频道
- Forum: Developers 分类
- GitHub: obsidianmd/obsidian-api
示例插件
| 项目 | 说明 |
|---|---|
| obsidian-sample-plugin | 官方示例插件 |
| obsidian-dataview | 复杂数据查询实现 |
| obsidian-templeter | 高级模板功能 |
| obsidian-git | 第三方服务集成 |
开发工作流
开发流程
mermaid
graph LR
A[创建项目] --> B[编写代码]
B --> C[本地测试]
C --> D{是否通过}
D -->|否| B
D -->|是| E[编写文档]
E --> F[发布]本地测试
- 编译 TypeScript:
npm run build - 复制文件到
.obsidian/plugins/your-plugin/ - 重启 Obsidian 或重新加载插件
- 测试功能
开发模式:npm run dev(监听文件变化自动编译)
调试方法
控制台调试:
- Windows/Linux:
Ctrl + Shift + I - macOS:
Cmd + Option + I - 移动端:设置 → 第三方插件 → 启用调试
常用调试:
console.log():输出调试信息debugger:设置断点this.registerEvent():事件追踪
插件类型
按功能分类
| 分类 | 功能 |
|---|---|
| 编辑增强 | 快捷操作、文本处理、格式转换 |
| 界面扩展 | 侧边栏面板、状态栏、自定义视图 |
| 数据管理 | 查询展示、数据同步、导入导出 |
| 外部集成 | API 对接、第三方服务、自动化工作流 |
按复杂度分类
| 复杂度 | 特征 | 代码量 |
|---|---|---|
| 简单 | 单一命令执行、简单设置项 | < 500 行 |
| 中等 | 多个功能模块、自定义视图 | 500-2000 行 |
| 复杂 | 完整工作流、数据存储、第三方服务集成 | > 2000 行 |
最佳实践
代码规范
typescript
// 1. 使用 TypeScript 严格模式
// tsconfig.json
{
"compilerOptions": {
"strict": true
}
}
// 2. 遵循命名规范
class MyPlugin extends Plugin {
// 私有属性用下划线前缀
private _setting: MySettings;
// 公共方法用 camelCase
public async loadData() {}
// 事件处理器用 on 前缀
private onFileChange(file: TFile) {}
}
// 3. 添加类型注释
interface MySettings {
enabled: boolean;
format: string;
}性能优化
typescript
// 1. 避免频繁 DOM 操作
// 不好
for (const item of items) {
container.createDiv({ text: item });
}
// 好
const fragment = document.createDocumentFragment();
for (const item of items) {
fragment.createDiv({ text: item });
}
container.appendChild(fragment);
// 2. 使用防抖/节流
import { debounce } from 'obsidian';
this.registerEvent(
this.app.vault.on('modify', debounce(
this.onFileChange.bind(this),
500
))
);
// 3. 正确清理资源
onunload() {
// 移除事件监听
this.unregisterEvents();
// 清理定时器
clearInterval(this.timer);
// 释放引用
this.views = null;
}错误处理
typescript
// 1. 捕获异步错误
async loadData() {
try {
const data = await this.app.vault.read(file);
return data;
} catch (error) {
console.error('Failed to load data:', error);
new Notice('加载失败,请检查文件是否存在');
return null;
}
}
// 2. 验证用户输入
function validateInput(value: string): boolean {
if (!value || value.trim() === '') {
new Notice('输入不能为空');
return false;
}
return true;
}
// 3. 优雅降级
if (!this.app.vault.getConfig('propertiesInDocument')) {
// 功能不可用时的替代方案
}常见问题
Q: 如何开始开发?
A:
Q: 如何调试插件?
A:
- 使用开发者工具(Ctrl+Shift+I)
- 查看 Console 面板
- 使用 console.log() 输出调试信息
- 参考调试技巧
Q: 如何发布插件?
A:
- 准备 README.md 和 LICENSE
- 提交到 GitHub
- 在社区仓库提交 PR
- 等待审核
- 参考发布插件