dv.el() 实现双栏布局,我的 dataviewjs 进阶之路

之前做了一个视频,有人问如何入门 dataviewjs

console.log(dv.current())
  1. 首先要看得懂 js,了解代理对象,数组的操作
  2. 从简单的 dataview 来,熟悉一下 sql 语句 Data Commands - Dataview
    1. 如果看英文困难 https://pkmer.cn/Pkmer-Docs/10-obsidian/obsidian社区插件/dataview/dataview基本语法/14---隐式字段/
    2. 现成例子,比如显示 3 天内修改的文件等玩转 Obsidian 08:利用 Dataview 打造自动化 HomePage - 少数派
  3. 进阶 dataviewjs ,先在控制台 console.log(dv.current()) 看 md 文件被解析成一个对象,里面有什么属性,看官网也行 Codeblock Reference - Dataview
  4. 在 dataviewjs 可以执行任何 js,那么,创建按钮(div),调用 ob 的 api 也可以
    1. 调用 dv.api obsidian-dataview/src/api/plugin-api.ts at master · blacksmithgu/obsidian-dataview · GitHub
    2. 想知道 dv 是怎么实现 tasklist 里点击完成后,对应的任务源文件也完成,obsidian-dataview/src/ui/views/task-view.tsx at 3c29f7cb5bb76f62b5342b88050e054a7272667f · blacksmithgu/obsidian-dataview · GitHub
    3. obsidian 的 api 查询 Vault | Obsidian 插件开发文档
    4. 显示美化,task.visual 展示元素样式 Colorcode tasks based on meta data - Dataview Example Vault
    5. 创建并打开文件 app.workspace.activeLeaf.openFile(await app.vault.create(newFilePath+"/Thouhts-" +date+".md","") 目前IO 操作的编程都是异步的了
  5. dataview 还提供了 dv.view 可以执行 js 和 css 文件,更加强大
    1. 比如,根据 dv 提供的数据,用 js 重新渲染了一个页面 GitHub - 702573N/Obsidian-Tasks-Timeline: A custom view build with Obsidian-Dataview to display tasks from Obsidian-Tasks and from your daily notes in a highly customisable timeline
3 个赞

界面预览

代码实现

```dataviewjs

const tasks = '"3-Tasks"'
const outputs = '"2-Outputs"'
const newFilePath = "2-Outputs"

let container =  dv.el("div","",{attr:{style: "display: flex; flex-wrap: wrap;"}})

let taskEl = container.createEl("div",{attr:{style: "flex:3;min-width:500px;margin-right:10px"}})
taskEl.createEl("h2",{text:"✅ Today"})

let tdata = dv.pages(tasks).sort(t => t.file.mtime,"desc").file.tasks.where( t => !t.completed)
console.log(tdata)
// let table =  dv.el("div","",{attr:{style: "display: flex; flex-wrap: wrap;"}})
dv.api.taskList( tdata,false, taskEl, dv.component)


let listEl = container.createEl("div",{attr:{style: "flex:1;min-width:250px"}})
listEl.createEl("h2",{text:"📚 Thoughts"})
listEl.createEl("button",{text:"创建新的笔记",attr:{style: "display:flex; margin-left: auto;margin-right:10px"}}).onclick = ()=> createFile()
// where file.mtime >= date(now) - dur(3 days) sort file.mtime DESC
let ldata = dv.pages(outputs).sort(t => t.file.mtime,"desc").limit(10).file.link
dv.api.list(ldata, listEl, dv.component)


let createFile =async () =>{
	const date = moment().format("yyyy-MM-DD");
	console.log(date)
	const fileName= newFilePath+"/Thoughts-" +date+".md"
	app.workspace.activeLeaf.openFile(await app.vault.exists(fileName) ? app.vault.getAbstractFileByPath(fileName) : await app.vault.create(fileName,"- "));
}
```


1 个赞

以后我就是你的原始粉丝了。

1 个赞

又增加了一些信息显示

这个靠右显示,用的是float实现,在间距不恰当的话,会挤到下一行。在最小修改的原则下,我没有想到更好的办法,他是 display:inline ,不能再有其他布局了。要改也行,但是整个 task-list-item 都要改

代码

tdata修改一下就好

let tdata = dv.pages(tasks).sort(t => t.file.mtime,"desc").file.tasks.where( t => !t.completed && t.text.trim()).map( t => {
	const sg =t.due ?  (dv.date( moment().format("yyyy-MM-DD")) - t.due) <0 ? 'in ' : 'out ' + Math.round(Math.abs(dur)/24/3600/1000) +" days" : ""
	const file = "<span style='background-color: grey;margin-left:10px'>" + (dv.page(t.path).project ?? dv.page(t.path).file.name )+ "</span>"
	const due = "<li style='float:right; opacity: 50% ;'>" + sg + file+"</li>"
	t.visual = t.text.replace(/\[[^\]]*::[^\]]*\]/,"").trim()   + due 
	return t 
	})
2 个赞

非常好内容,用 flex 进行自适应分栏的方法学习到了,感谢分享! :smiling_face_with_three_hearts:

抓个虫,新的这段代码里有个变量 dur ,需要在前面定义一下不然会报错。

// 周期限制
const dur = 3;

(不过这是干啥的?) :thinking:


另一个是有的人可能会使用「取消的任务」语法(Tasks 插件的特性),像这样:

- [-] 这个任务取消了

这些任务也会被显示进去:

想要排除的话,可以在筛选条件里添加 : t.status != "-"

如下:

.file.tasks.where( t => !t.completed && t.status != "-" && t.text.trim())
1 个赞

你说的对,精简代码的时候,不小心搞错,是为了计算 超出几天的暂存变量,可以优化掉

const dur = dv.date( moment().format(“yyyy-MM-DD”)) - t.due

1 个赞