使用dataview可以通过文件名等方式,得到某个文件内的全部任务。
我希望实现类似这样的效果:
右边的文件是没有切换的,可以跟随编辑文件的变化而变化显示文件内的任务情况,可以做到么?
没找到特别直观的实现方式, 我目前卡在 “怎么让侧栏某个 dv 块, 在主栏的某个标签页改变后, 就自动重新计算一次” 这事 (能实现, 但不知道怎么弄简单点)
我目前想到几个办法, 从简单到复杂:
A 如果目标就是让侧栏同步显示主栏笔记的待办任务
那其实可以不管 dataview, 许多插件已经做了类似的事
例如 ivan-lednev/obsidian-day-planner 可以把当前笔记的待办直接列出来到侧栏 (该插件主要目标是给带 HH:mm 格式的任务排个可视化时间轴, 但也可以列出当前笔记所有无时间戳的任务)
B 如果目标是让侧栏笔记作为主栏的伴侣笔记, 一定要以 dataview 去汇总主栏的某些信息
做到下面几件事就行
// 以下是侧栏辅助笔记的 dataviewjs
const activePage = app.workspace.getActiveFile();
if (activePage) {
const currentFile = dv.page(activePage.path).file;
if (currentFile.tasks.length) {
dv.paragraph(`Find ${currentFile.tasks.length} Task(s) on ${activePage.basename}`);
dv.taskList(currentFile.tasks, false);
} else {
dv.paragraph(`(No Tasks on Page ${activePage.path})`);
}
} else {
dv.paragraph("(No active page)");
}
然后在标签页变动时, 设法触发一次 dv 块的刷新
// 以下在 console 里执行一下, 或利用任何带运行脚本功能的插件
// 于是此后每当 'active-leaf-change' 发生时, 就执行 dv 刷新
// 参考 https://forum-zh.obsidian.md/t/topic/25760/35
app.workspace.onLayoutReady(() => {
let stTimer;
app.workspace.on('active-leaf-change', async (activeLeaf) => {
// 定时防止无效触发,只取最后一个触发
if(stTimer) clearTimeout(stTimer);
stTimer = setTimeout(() => {
new Notice('将要执行 dataview refresh');
app.commands.executeCommandById("dataview:dataview-force-refresh-views");
}, 500)
})
})
若不需频繁使用, 直接在 Ob 命令行手动执行 “Dataview Force Refresh” 也行
C 跟方案 B 类似的另一个办法, 当标签页变更后, 向侧栏笔记写入信息
// 以下是侧栏辅助笔记的 dataviewjs
// 在侧栏笔记里写一个文档属性, 假设叫 note_path_for_task_sum
// ---
// note_path_for_task_sum: xxx.md
// ---
// 侧栏 dv 块始终汇总该 note_path_for_task_sum 路径内的待办
const page = dv.page(dv.current().file.frontmatter.note_path_for_task_sum);
if (page) {
const currentFile = page.file;
// 以下都跟 方案 B 一样......
然后在标签页变化后, 向侧栏笔记的 YFM 里写下指定属性
可以考虑用 processFrontMatter
, 我从这里学来的 快速操作笔记的元数据,汇总近期完成事项 - 经验分享
// 参考 方案 B, 以下在 console 里执行一下, 或利用任何带运行脚本功能的插件
app.workspace.onLayoutReady(() => {
let stTimer;
app.workspace.on('active-leaf-change', async (activeLeaf) => {
if(stTimer) clearTimeout(stTimer);
stTimer = setTimeout(() => {
const activePage = app.workspace.getActiveFile();
const sidebarNotePath = "path/to/侧栏笔记.md";
const fileObj = app.vault.getAbstractFileByPath(sidebarNotePath);
app.fileManager.processFrontMatter(fileObj, fm => {
fm["note_path_for_task_sum"] = activePage.path;
new Notice(`YFM update note_path_for_task_sum => ${activePage.path}`);
})
}, 500)
})
})
方案 C 一旦侧栏笔记的内容被修改, dv 就会自动重算, 于是省了强制 dv 刷新那一步, 这办法的优势在于可控性更好, 比如甚至可以实现: 在侧栏汇总 “最近N个访问过的文件” 里的待办任务
非常感谢大佬,不用dataview其实也行,只是没想到可以用day planner来做。
看到这个想起来,像是 QuiterOutline ( github.com/guopenghui/obsidian-quiet-outline )这类插件都是在侧栏的同时,可以实时显示 当前激活文件 的数据的,或许也可以参考一下它们的实现原理?