一、JavaScript操作
map
对于所有元素执行相同操作
如[1,2,3].map(p=>p+1)
可以得到[2,3,4]
,这个 p 代指操作时的每一个元素,p=>p+1
本质上是个函数
再比如dv.pages(`"目标文件夹"`).map(p=>p.file.tags)
得到目标文件夹下所有笔记的标签
filter
只保留返回为 true 的元素
如dv.pages(`"目标文件夹"`).filter(p=>p.file.tags.includes('标签')
只保留了标签中含标签
的那些文件数据
JavaScript 其他教程:JavaScript 数组参考手册
二、快速入门
1. 显示Hello World
任意新建一个文档将下面的内容复制粘贴并运行。
greet:: Hello World!
- [ ] `= this.greet`
const page = dv.current()
const inlineGreet = page["greet"]
console.log(inlineGreet)
dv.header(2, inlineGreet)
dv.list([inlineGreet])
dv.el("span", `- [ ] ${inlineGreet}`)
dv.taskList(page.file.tasks)
dv.table(["问候"], [[inlineGreet]])
下面我们来分析一下上述示例:
首先,我们在文档中创建了一个内联属性 greet
,然后创建了一个任务并通过内联 DQL 查询出 greet
属性并作为任务的名称。
接下来,我们通过调用 dv.current()
函数获取脚本当前正在执行的页面的页面信息,这相当于调用 dv.page("当前文档名")
函数。然后赋值给常量 page
,紧接着读取了页面中的内联属性 greet
并赋值给常量 inlineGreet
。
第一个输出使用浏览器的控制台作为载体,通过调用 JavaScript 的 console.log()
函数来实现。如果你不知道怎么显示开发者工具,1)在 Windows 或 Linux 下可以使用快捷键 Ctrl+Shift+I;2)macOS 请使用Cmd+Opt+I。
接下来我们分别使用了 div.header(2, inlineGreet)
函数来将问候输出为二级标题;使用 dv.list([inlineGreet])
将其输出为列表元素;使用 dv.el("span", ...)
函数来将其输出为任务(这里只是为了演示,通常我们是从文档中获取任务);使用 dv.taskList(p
函数将页面中的任务查询出来;最后使用 dv.table(["问候"], [[inlineGreet]])
函数将其输出为表格显示。
2. 读取属性
在 Obsidian 中我们可以在 Fronat matter 中定义 YAML 属性,也可以使用 Dataview 提供的内联属性在文体任意有效的位置定义属性。
下面是一段包含了各种属性的文档内容片段,我们将基于此进行讲解。
---
---
description: 测试描述
tags:
- 标签1
- 标签2
---
inlineProp1:: 测试
inline_test:: 下划线命名测试
InlineTest2:: 大写字母开头命名测试
Test Long Split Words:: 不规则变量名测试
**Bold Text**:: 加粗文本测试
这是内联字段 [inlineProp2:: 在文本内部]
我的名称不可见 (inlineProp3:: 我的变量名不可见)
- 在列表中定义标签 #标签3 和内联变量 [inlineProp4:: 在列表内]
- [ ] 在任务中定义标签 #标签4 和内联变量 [inlineProp5:: 在任务内]
外链:[[2022-01-06]]
我们使用dv.current()
获取当前页面的数据,然后使用Object.keys()
方法来遍历所有属性。
```dataviewjs
Object.keys(dv.current()).forEach(key => {
console.log(key);
})
[!tip] dv.current()为dv.page(“文档路径”)的便捷方法
我们在命名变量时分别使用了驼峰式命名法、帕斯卡命名法、下划线命令法以及带有空格的属性名。从结果来看当前页面中定义的属性都在了,而且输出的数量远比我们定义的多,这是因为对于不规则的属性名,Dataview 内部进行了规范化。在 JavaScript 中属性通常以 对象.属性名
的方式来读取,同时也可以使用 对象['属性名']
的方式,后者在通常用于动态计算属性名和特殊属性名读取。
```dataviewjs
const page = dv.current()
console.log(page['test-long-split-words']) // 不规则变量名测试
console.log(page['Test Long Split Words']) // 不规则变量名测试
console.log(page.inline_test) // 下划线命名测试
console.log(page.InlineTest2) // 大写字母开头命名测试
console.log(page.inlineprop1) // 测试
以 Hello World
字符串为属性变量名举例,建议使用 hello-world
,其次是 helloWorld
/ HelloWorld
/ hello_world
这三者可自行选用,在不同的编程语言环境都有其适用的场景。
为什么选择以 hello-world
的方式一方面是 YAML 中定义属性支持,然后 DQL 内联查询支持(= hello-world
), 再一个很重要的原因这是官方内部默认使用(比如将带空格的属性转化后的结果)。虽然方便了 DQL 的读取,但是使用 API 读取时,我们需要额外多输入中括号和引号(dv.current()['hello-world']
),这种成本通常可以忽略不计。
我们在前面通过遍历 dv.current()
在控制台显示所有属性,接下来我们看一下如何获取指定区域的属性。
(1)YAML中的属性读取
Obsidian 中 tags
,cssclasses
和 aliases
是内置的默认属性,如果要获取自定义或者第三方插件提供的属性,则需要提前知识有哪些属性名,因为所有属性全挂在了 dv.current()
返回的对象中。要获取 YAML 中的属性我们需要使用 file.frontmatter
属性:
```dataviewjs
console.log(dv.current().file.frontmatter) // {description: '测试描述', tags: Array(2), hello-world: '你好呀'}
(2)列表和任务中的属性读取
Dataview 将任务作为一种特殊的列表来处理,可以使用 page.file.lists
来获取当前页面中的列表数据,使用 page.file.tasks
来获取任务数据。在获取的列表数据同时包含了所有的任务,可通过基属性 task
是否为 true
来判断当前列表是否为任务项。
在列表中定义的属性会挂载在当前列表对象下,而标签则位于 tags
属性中,下面我们分别读取列表和任务中的标签和属性。
```dataviewjs
const lists = dv.current().file.lists;
const tasks = dv.current().file.tasks;
lists.forEach(list => {
if (list.task) {
console.log(list.tags) // ['#标签4']
console.log(list.inlinbobyai eProp5) // 在任务内
} else {
console.log(list.tags) // ['#标签3']
console.log(list.inlineProp4) %% 在列表内 %%
}
})
tasks.forEach(task => {
console.log(task.tags) %% ['#标签4'] %%
console.log(task.inlineProp5) %% 在任务内 %%
})
(3)外链文档中的属性读取
在示例中我们使用外部链接引用了一篇笔记的地址,现在我们通过遍历page.file.outlinks
属性来获取外链的元数据,然后将其path
属性传入dv.page()
中来获取页面的所有信息,接着使用file.tags
来读取标签值。
```dataviewjs
const links = dv.current().file.outlinks
links.forEach(link => {
console.log(dv.page(link.path).file.tags.array()) // ['#daily', '#journal']
})
3. 查询数据输出
在 DQL 中我们可以将查询的结果以表格、任务和日历的方式渲染到当前查询脚本所在的代码块位置。在 JavaScript 中没有对应的日历视图 API,只有 dv.list()
方法对应 LIST
语句,dv.taskList()
方法对应 TASK
语句以及 dv.table()
方法对应 TABLE
语句。虽然没有提供日历输出的方法,但是我们可以 API 中执行 DQL 查询语句变相实现。
(1)dv.list(element,text)方法
用于将结果渲染成列表,可接收 JavaScript 数组及 DataArray 类型。
```dataviewjs
const vanillaArray = [1, 2, [3, 4, 5, [6]]]
const dvArray = dv.array(vanillaArray)
dv.list(dvArray)
// dv.list(vanillaArray)
(2)dv.taskList(tasks,groupByFile)方法
用于将结果渲染成任务列表,数据源必须从 page.file.tasks
中获取,默认情况下如果数据从多个文档中获取,则会按文档名进行分组,当然也可以将第二个参数指定为 false
来禁用分组。
下面根据 #daily
标签查询任务来展示 groupByFile
参数的作用,查询语句为:dv.taskList(dv.pages("#daily").file.tasks)
, 结果如下:
从结果来看,在指定了第 2 个参数为false
后,任务的顺序发生了变化,右则的截图中的任务可能来自于多个页面中。
(3)dv.table(headers,elements)方法
用于将结果渲染成表格数据,headers
为一个数组,表示表头名称,而elements
为表格数据,其值为数组,数组的每一项值同样为数组,用于表示表格的行数据。
```dataviewjs
const headers = ["姓名", "年龄", "性别", "爱好"]
const data = [ ["张三", 20, "男", "打篮球"],
["李四", 25, "女", "踢足球"],
["王五", 30, "男", "游泳"]
]
dv.table(headers, dv.array(data))
(4)日历输出
Dataview 并没有提供dv.calendar()
方法来将查询的数据渲染为日历显示,但是我们可以通过dv.execute(source)
来执行 DQL 查询,实现在 API 中渲染日历的功能。
```dataviewjs
const query = `
CALENDAR file.day
FROM "10 Example Data/dailys"
`
dv.execute(query)
4. HTML渲染
我们使用的表格、任务和列表在 Obsidian 中实际上都是最终用特定的 HTML 标签元素表示的,比如说表格为 <table></table>
标签,列表分为有符号列表 <ol></ol>
,无符号列表 <ul></ul>
,定义列表 <dl></dl>
,像日历这种比较复杂的组件则是由多个 <div></div>
等元素嵌套而成的。
我们在 Obsidian 页面编辑时可以输入标题(1-6 号),正文内容,插入图片、代码等,这都可以使用 API 来动态设置。
dv.header(level, text)
用于渲染标题,其中level
取值为1-6
。dv.paragraph(text)
用于渲染段落,即<p></p>
标签。dv.span(text)
用于渲染行内元素,即<span></span>
标签。dv.el(element, text)
用于渲染指定的<element></element>
标签内容。
```dataviewjs
dv.header(2, "HTML渲染")
dv.paragraph("HTML段落元素渲染")
dv.span("行内容元素渲染")
const html = `
<div style="display: flex; align-items: flex-start;margin: 10px 0;">
<div width="60" height="60">
<img src="https://via.placeholder.com/60" style="border-radius:50%;" alt="Avatar">
</div>
<div style="margin-left: 10px;">
<div style="font-size: 18px; font-weight: bold;">User name</div>
<div style="font-size: 14px; color: #666;">User Description</div>
</div>
</div>
`
dv.el("div", html)
5. Markdown原始内容输出
在 Obsidian 中我们可以通过标题栏右则的【更多选项】-> 【源码模式】来切换至 Markdown 原始内容视图。我们可以将任何 Markdown 文本内容渲染到页面中。
```dataviewjs
const raw = `
## 2号标题
这是文本内容。
- 列表
- [x] 任务
**文字加粗**
双链:[[2022-08-03]]
## 表格
| 姓名 | 年龄 | 性别 | 爱好 |
| -- | -- | -- | --- |
| 张三 | 20 | 男 | 打篮球 |
| 李四 | 25 | 女 | 踢足球 |
| 王五 | 30 | 男 | 游泳 |
`
dv.paragraph(raw)
结果:
上面我们是手动提供的 Markdown 原始数据进行演示的,如果我们相要获取查询页面中的列表、任务或者表格的原始数据,该如何作呢?Dataview 已经为我们准备好了开箱
dv.markdownTable(headers, values)
将结果输出为原始的 Markdown 表格表示形式,参数同dv.table()
。dv.markdownList(values)
将结果输出为原始的 Markdown 列表形式,即:- xxx
。dv.markdownTaskList(tasks)
将结果输出为原始的 Markdown 任务形式,即:- [ ] xxx
或者- [x] xxxx
。
将上述输出的 Markdown 原始数据使用 dv.paragraph()
挂载即可在页面中显示,当然也可以使用 dv.el()
选择其它的标签来作为容器。
6. 解析DQL查询语句
DQL(数据查询语言)为普通用户提供了一种便捷的查询方式,使用户无需编写复杂的代码即可满足大部分数据管理需求。这种方式不仅简化了操作过程,还提高了使用效率和友好性。
在有些场景下我们使用 DQL 查询语句会更加高效,可以将其结合在代码中发挥特定的作用。当然,也有些场景下我们必须用到,如前面提到的日历渲染。Dataview 为我们提供了以下几个方法来解析 DQL 查询语句或者 DataviewJS 语句。
dv.execute(source)
执行任意数据视图查询并将视图嵌入到当前页面中。dv.executeJs(source)
执行任意 DataviewJS 查询并将视图嵌入到当前页面中。
使用方式:
```dataviewjs
dv.executeJs("dv.list([1, 2, 3, 4])") // 相当于 dv.list([1, 2, 3, 4])
dv.execute("TASK FROM #daily")
三、同系列
- [[Obsidian插件Dataview —— 安装与设置(一)]]
- [[Obsidian插件Dataview —— YAML简介(二)]]
- [[Obsidian插件Dataview —— 认识属性(三)]]
- [[Obsidian插件Dataview —— 数据查询(四)]]
- [[Obsidian插件Dataview —— DQL查询语言详解(五)]]
- [[Obsidian插件DataviewJS —— TypeScript速成(六)]]
- [[Obsidian插件Dataview —— 深入理解DataviewJS(七)]]
- [[Obsidian插件Dataview —— DataArray接口介绍(九)]]
- [[Obsidian插件Dataview —— Dataviewjs JavaScript API 进阶用法(十)]]
- [[Obsidian插件Dataview —— Luxon库介绍(十一)]]
- [[Obsidian插件Dataview —— 实用案例讲解(初级篇)(十二)]]
- [[Obsidian插件Dataview —— 实用案例讲解(中级篇)(十三)]]
- [[Obsidian插件Dataview —— 实用案例讲解(高级篇)(十四)]]
四、参考
- obsidian api 文档:App – Developer Documentation
- 插件 api 文档:ObsidianDataview文档中文 – 知乎
必须 注册 为本站用户, 登录 后才可以发表评论!