Settings API 深度指南
本文汇总 Obsidian Settings API 的完整用法,从基础设置项到高级动态设置面板。
快速回顾
以下内容在其他教程中已详述,这里简要列出接口:
typescript
import { Plugin, PluginSettingTab, Setting } from 'obsidian';
export default class MyPlugin extends Plugin {
settings: MyPluginSettings;
async onload() {
this.addSettingTab(new MySettingTab(this.app, this));
}
}基础设置类型
文本输入 → TextComponent
typescript
new Setting(containerEl)
.setName('API Key')
.setDesc('输入你的 API 密钥')
.addText(text => text
.setPlaceholder('sk-...')
.setValue(this.plugin.settings.apiKey)
.onChange(async (value) => {
this.plugin.settings.apiKey = value;
await this.plugin.saveSettings();
}));文本输入扩展属性:
text.inputEl.type = 'password'— 隐藏输入内容.setDisabled(true)— 禁用编辑
开关 → ToggleComponent
typescript
new Setting(containerEl)
.setName('启用功能')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enabled)
.onChange(async (value) => {
this.plugin.settings.enabled = value;
await this.plugin.saveSettings();
}));下拉选择 → DropdownComponent
typescript
new Setting(containerEl)
.setName('主题模式')
.addDropdown(dropdown => dropdown
.addOption('light', '浅色')
.addOption('dark', '深色')
.addOption('system', '跟随系统')
.setValue(this.plugin.settings.theme)
.onChange(async (value) => {
this.plugin.settings.theme = value;
await this.plugin.saveSettings();
}));滑块 → SliderComponent
typescript
new Setting(containerEl)
.setName('字体大小')
.addSlider(slider => slider
.setLimits(12, 32, 1) // min, max, step
.setValue(this.plugin.settings.fontSize)
.setDynamicTooltip() // 拖动时显示值
.onChange(async (value) => {
this.plugin.settings.fontSize = value;
await this.plugin.saveSettings();
}));文本域 → TextAreaComponent
typescript
new Setting(containerEl)
.setName('自定义 CSS')
.addTextArea(text => {
text
.setPlaceholder('输入 CSS 代码...')
.setValue(this.plugin.settings.customCSS)
.onChange(async (value) => {
this.plugin.settings.customCSS = value;
await this.plugin.saveSettings();
});
text.inputEl.rows = 6;
text.inputEl.cols = 40;
});颜色选择器 → ColorComponent
typescript
new Setting(containerEl)
.setName('强调色')
.addColorPicker(color => color
.setValue(this.plugin.settings.accentColor)
.onChange(async (value) => {
this.plugin.settings.accentColor = value;
await this.plugin.saveSettings();
}));按钮 → ButtonComponent 和 ExtraButtonComponent
typescript
// 操作按钮
new Setting(containerEl)
.setName('清除缓存')
.addButton(button => button
.setButtonText('清除')
.setCta() // 突出样式
.onClick(() => {
this.clearCache();
}));
// 图标按钮(在 Setting 右侧)
new Setting(containerEl)
.setName('API 地址')
.addExtraButton(button => button
.setIcon('reset')
.setTooltip('重置为默认')
.onClick(() => {
// ...
}));信息提示 → addDesc / addMomentColor
typescript
new Setting(containerEl)
.setName('已连接 ✅')
.setDesc(new DocumentFragment() // 支持 HTML
.createEl('span', { text: '状态正常' })
.createEl('br')
.createEl('a', { href: 'https://example.com', text: '查看文档' })
);组合设置项
一个 Setting 可以包含多个组件:
typescript
new Setting(containerEl)
.setName('每日笔记模板')
.setDesc('选择模板并指定目标文件夹')
.addText(text => text
.setPlaceholder('文件夹路径')
.setValue(this.plugin.settings.folder))
.addDropdown(dropdown => dropdown
.addOption('daily', '日记模板')
.addOption('weekly', '周记模板')
.setValue(this.plugin.settings.template));条件显示 — 动态设置项
根据用户选择显示/隐藏关联设置:
typescript
class MySettingTab extends PluginSettingTab {
display(): void {
const { containerEl } = this;
containerEl.empty();
// 主开关
new Setting(containerEl)
.setName('启用高级模式')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.advancedMode)
.onChange(async (value) => {
this.plugin.settings.advancedMode = value;
await this.plugin.saveSettings();
this.display(); // 重新渲染整个面板
}));
// 条件显示
if (this.plugin.settings.advancedMode) {
new Setting(containerEl)
.setName('高级选项 A')
.addText(text => text
.setValue(this.plugin.settings.advancedA)
.onChange(async (value) => {
this.plugin.settings.advancedA = value;
await this.plugin.saveSettings();
}));
}
}
}注意:调用
this.display()重新渲染会导致焦点丢失。对于少量选项,可以用.setDisabled()或 CSS 控制显隐。
动态列表 — 添加/删除条目
typescript
new Setting(containerEl)
.setName('排除的文件夹')
.setDesc('这些文件夹将被忽略')
.addButton(button => button
.setButtonText('添加')
.setCta()
.onClick(() => {
this.plugin.settings.excludeFolders.push('');
this.plugin.saveSettings();
this.display();
}));
this.plugin.settings.excludeFolders.forEach((folder, index) => {
new Setting(containerEl)
.addText(text => text
.setValue(folder)
.setPlaceholder('文件夹路径')
.onChange(async (value) => {
this.plugin.settings.excludeFolders[index] = value;
await this.plugin.saveSettings();
}))
.addExtraButton(button => button
.setIcon('trash')
.setTooltip('删除')
.onClick(async () => {
this.plugin.settings.excludeFolders.splice(index, 1);
await this.plugin.saveSettings();
this.display();
}));
});设置迁移
当插件升级时,旧版本用户的数据结构可能不同:
typescript
// settings.ts
export interface MyPluginSettings {
version: number; // 用于版本追踪
apiKey: string;
// v2 新增
endpoint?: string;
// v1 旧字段(已重命名)
template?: string;
}
export const DEFAULT_SETTINGS: MyPluginSettings = {
version: 2,
apiKey: '',
endpoint: 'https://api.example.com',
};typescript
// main.ts
async onload() {
await this.loadSettings();
// 从旧版本迁移
if (this.settings.version < 2) {
if (this.settings.template) {
// 迁移旧字段
this.settings.apiKey = this.settings.template;
delete this.settings.template;
}
this.settings.version = 2;
await this.saveSettings();
}
}迁移检查清单:
- 每次设置结构变化时递增
version字段 - 在
onload中检查版本并按步骤迁移 - 用可选属性
?标记新增字段,避免undefined错误 - 迁移后立即调用
saveSettings()
Settings UI 模式
分组标题
typescript
// 方法 1:使用 Setting.setHeading()
new Setting(containerEl)
.setName('API 配置')
.setHeading();
// 方法 2:手动创建标题
containerEl.createEl('h2', { text: 'API 配置' });
containerEl.createEl('p', {
text: '配置第三方 API 的连接参数',
cls: 'setting-item-description'
});带状态指示
typescript
new Setting(containerEl)
.setName('连接状态')
.setDesc(this.plugin.settings.isConnected
? '✅ 已成功连接到服务器'
: '❌ 连接失败,请检查配置')
.addButton(button => button
.setButtonText('测试连接')
.onClick(async () => {
button.setButtonText('测试中...');
button.setDisabled(true);
try {
await this.testConnection();
new Notice('连接成功');
} catch {
new Notice('连接失败');
}
button.setButtonText('测试连接');
button.setDisabled(false);
this.display(); // 刷新状态文字
}));重置按钮
typescript
new Setting(containerEl)
.setName('重置设置')
.setDesc('将所有设置恢复为默认值')
.addButton(button => button
.setButtonText('重置')
.setWarning() // 红色警告样式
.onClick(async () => {
this.plugin.settings = { ...DEFAULT_SETTINGS };
await this.plugin.saveSettings();
this.display();
new Notice('设置已重置');
}));Setting 装饰方法
Setting 类提供的链式方法:
| 方法 | 说明 |
|---|---|
.setName(name) | 设置标题(支持字符串或 DocumentFragment) |
.setDesc(desc) | 设置描述文字 |
.setClass(cls) | 添加 CSS 类名 |
.setTooltip(tooltip) | 添加悬停提示 |
.setDisabled(disabled) | 禁用整个设置项 |
.setHeading() | 将当前项渲染为分组标题 |
.addButton(cb) | 添加按钮 |
.addToggle(cb) | 添加开关 |
.addText(cb) | 添加文本输入 |
.addTextArea(cb) | 添加文本域 |
.addDropdown(cb) | 添加下拉框 |
.addSlider(cb) | 添加滑块 |
.addColorPicker(cb) | 添加颜色选择 |
.addExtraButton(cb) | 添加图标按钮 |
.addMomentColor(cb) | 添加瞬时颜色选择器 |
.then(cb) | 在渲染完成后执行回调 |
最佳实践
typescript
export class MySettingTab extends PluginSettingTab {
plugin: MyPlugin;
constructor(app: App, plugin: MyPlugin) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const { containerEl } = this;
containerEl.empty();
// ✅ 先清空再渲染,避免重复元素
// ✅ 每次 onChange 都调用 saveSettings()
// ✅ 复杂面板可拆分为多个私有方法
this.addAPISection(containerEl);
this.addDisplaySection(containerEl);
this.addAdvancedSection(containerEl);
}
private addAPISection(el: HTMLElement): void {
el.createEl('h2', { text: 'API 配置' });
// ...
}
private addDisplaySection(el: HTMLElement): void {
el.createEl('h2', { text: '显示设置' });
// ...
}
private addAdvancedSection(el: HTMLElement): void {
el.createEl('h2', { text: '高级设置' });
// ...
}
}与插件教程的关系
| 你需要的场景 | 参考文档 |
|---|---|
| 第一个设置面板怎么建 | 插件开发教程 |
| 完整的高级面板实现 | 插件开发进阶 |
| 国际化设置面板 | 插件国际化 |
| 设置拖拽排序 | 插件高级技巧 |