Skip to content

Properties 高级技巧

本文面向已熟悉 Properties 基本用法的用户,介绍高级技巧和自动化工作流。

前置知识

本文假设你已了解 Properties 的基本概念。如需入门,请先阅读 Properties 完整指南

属性批量操作

使用 Templater 批量修改

javascript
<%*
// 批量为文件夹中的笔记添加属性
const folder = app.vault.getAbstractFileByPath("Projects");
if (folder && folder.children) {
  for (const file of folder.children) {
    if (file.extension === "md") {
      await app.fileManager.processFrontMatter(file, (fm) => {
        if (!fm.type) fm.type = "project";
        if (!fm.status) fm.status = "active";
      });
    }
  }
  new Notice("批量属性更新完成");
}
%>

使用 DataviewJS 批量查询

dataviewjs
// 查询所有缺少 type 属性的笔记
const pages = dv.pages()
  .where(p => !p.type && p.file.folder !== "Templates");

dv.table(
  ["文件", "文件夹", "修改时间"],
  pages.map(p => [
    p.file.link,
    p.file.folder,
    p.file.mtime
  ])
);

使用 processFrontMatter 批量更新

javascript
// 在 Obsidian 开发者控制台中执行
const files = app.vault.getMarkdownFiles();
let count = 0;

for (const file of files) {
  const cache = app.metadataCache.getFileCache(file);
  if (!cache?.frontmatter?.tags) {
    await app.fileManager.processFrontMatter(file, (fm) => {
      fm.tags = ["untagged"];
    });
    count++;
  }
}

console.log(`已为 ${count} 个笔记添加 tags 属性`);

属性继承与关联

父子关联

通过链接属性实现父子笔记关联:

yaml
---
# project-a.md
type: project
name: 项目A
deadline: 2024-06-30
team: [张三, 李四]
---
yaml
---
# task-1.md
type: task
project: "[[project-a]]"
status: in-progress
---

使用 Dataview 查询关联属性

dataview
TABLE 
  status AS "状态",
  project.deadline AS "项目截止日期",
  project.team AS "团队"
FROM "Tasks"
WHERE project
SORT project.deadline ASC

嵌套属性

使用缩进创建嵌套结构:

yaml
---
title: 项目文档
meta:
  author: 张三
  version: 1.0
  updated: 2024-02-15
---

注意

Dataview 对嵌套属性的查询支持有限。建议将常用查询属性放在顶层。

Bases 与 Properties 结合

版本要求

Bases 功能需要 Obsidian 1.7.2 及以上版本。

创建属性驱动的数据库

  1. 创建 .base 文件:
yaml
type: base
sources:
  - path: Projects/
    properties:
      - name: title
        type: text
      - name: status
        type: select
        options: [active, completed, on-hold]
      - name: deadline
        type: date
      - name: team
        type: list
  1. 在笔记中嵌入 Bases 视图:
base
from: Projects/
where: status = "active"
sort: deadline asc
columns: [title, status, deadline, team]

看板视图

使用 Bases 的看板视图按属性分组:

base
from: Tasks/
group: status
columns: [title, priority, due, project]

CSS 样式化

根据属性值改变笔记外观

yaml
---
cssclass: wide-page
status: draft
---
css
/* 宽页面布局 */
.wide-page .markdown-preview-view {
  max-width: 100%;
}

/* 根据状态标记笔记 */
[data-status="draft"] .nav-file-title {
  color: var(--text-faint);
  font-style: italic;
}

[data-status="important"] .nav-file-title {
  color: var(--color-red);
  font-weight: bold;
}

隐藏已完成任务

yaml
---
cssclass: hide-completed
---
css
.hide-completed .task-list-item.is-checked {
  display: none;
}

安装 Supercharged Links 插件后,可以根据属性值为链接添加样式:

css
/* 高优先级任务链接 */
.data-link-priority[data-link-priority="high"] {
  color: var(--color-red) !important;
  font-weight: bold;
}

/* 已完成项目链接 */
.data-link-status[data-link-status="completed"] {
  text-decoration: line-through;
  opacity: 0.6;
}

自动化工作流

Templater 动态属性

javascript
<%*
// 根据文件夹自动设置属性
const folder = tp.file.folder();
const fileName = tp.file.title;

// 自动推断类型
const typeMap = {
  "Projects": "project",
  "Daily": "daily-note",
  "Meetings": "meeting",
  "Reading": "reading-note"
};

const noteType = typeMap[folder] || "note";
tR += `type: ${noteType}\n`;

// 自动关联项目
if (folder.startsWith("Projects/")) {
  const projectName = folder.split("/")[1];
  tR += `project: "[[${projectName}]]"\n`;
}
%>

QuickAdd 属性工作流

使用 QuickAdd 插件创建带属性捕获的工作流:

  1. 创建 QuickAdd Choice → Macro
  2. 添加「属性捕获」步骤
  3. 配置要捕获的属性名和类型
  4. 设置模板和目标文件夹

定时属性更新

使用 Obsidian 的 registerInterval 定时更新属性:

typescript
// 插件代码示例
this.registerInterval(
  window.setInterval(async () => {
    const file = this.app.workspace.getActiveFile();
    if (file) {
      await this.app.fileManager.processFrontMatter(file, (fm) => {
        fm.last_reviewed = new Date().toISOString().split('T')[0];
      });
    }
  }, 60000) // 每分钟检查
);

属性迁移

从标签迁移到属性

javascript
<%*
// 将 #project/xxx 标签转换为 project 属性
const files = app.vault.getMarkdownFiles();
let migrated = 0;

for (const file of files) {
  const cache = app.metadataCache.getFileCache(file);
  const tags = cache?.frontmatter?.tags || [];
  
  const projectTags = tags.filter(t => t.startsWith("project/"));
  if (projectTags.length > 0) {
    await app.fileManager.processFrontMatter(file, (fm) => {
      fm.project = projectTags[0].replace("project/", "");
      fm.tags = tags.filter(t => !t.startsWith("project/"));
    });
    migrated++;
  }
}

new Notice(`已迁移 ${migrated} 个笔记的属性`);
%>

属性重命名

javascript
<%*
// 将 "date" 属性重命名为 "created"
const files = app.vault.getMarkdownFiles();
let count = 0;

for (const file of files) {
  const cache = app.metadataCache.getFileCache(file);
  if (cache?.frontmatter?.date) {
    await app.fileManager.processFrontMatter(file, (fm) => {
      fm.created = fm.date;
      delete fm.date;
    });
    count++;
  }
}

new Notice(`已重命名 ${count} 个笔记的属性`);
%>

属性管理最佳实践

命名规范

yaml
# ✅ 推荐
created_date: 2024-02-15
modified_date: 2024-02-20
due_date: 2024-02-25

# ❌ 不推荐
created: 2024-02-15
date_modified: 2024-02-20
deadline: 2024-02-25

属性标准库

为团队或个人定义标准属性集:

属性名类型用途必填
titletext笔记标题
typetext笔记类型
tagslist标签
createddate创建日期
modifieddate修改日期
statustext状态按类型
prioritynumber优先级 1-5
projectlink关联项目

避免属性膨胀

  • 不超过 10 个属性/笔记(日常笔记)
  • 使用嵌套属性组织相关字段
  • 定期清理不再使用的属性
  • 通过模板统一属性集

常见问题

属性中文无法正常显示?

确保文件编码为 UTF-8。建议使用英文属性名,中文属性值。

嵌套属性如何查询?

Dataview 查询嵌套属性使用点语法:

dataview
TABLE meta.author, meta.version
WHERE meta

属性和标签如何选择?

场景用标签用属性
分类/筛选
结构化数据
数值/日期
链接关联
简单分类

相关资源