[[寡人]]
最新的图文版:https://wws.lanzoui.com/ivW46spygfi
> 翻译自 [Dataview](https://blacksmithgu.github.io/obsidian-dataview/intro/),翻译了一部分,有不对的自行辨别,希望可以帮助更多人使用 dataview 这款优秀的 obsidian 插件。
# dataview
## 查询语法格式
该插件的 dataview 代码块的使用方法类似于SQL,下面是一个普通的SQL语句:
```sql
SELECT field1 (AS "自定义显示名称"),field2……,fieldn
FROM tablename
WHERE field1==value1 or field2==value2
ORDER BY field1 DESC
……(LIMIT 10)
```
dataview的查询格式如下:
```sql
```dataview
TABLE|LIST|TASK <field> (AS "Column Name"), <field>, ..., <field>
FROM <source>
WHERE <expression>
SORT <expression> (ASC/DESC)
... other data commands
```
```
可以看到,二者很像,可以清楚的看到其中的对应关系,tablename对应着source等等。
## 关键字
介绍 dataview 查询格式中的关键字的用途。
```sql
```dataview
TABLE|LIST|TASK <field> (AS "Column Name"), <field>, ..., <field>
FROM <source>
WHERE <expression>
SORT <expression> (ASC/DESC)
... other data commands
```
```
### 1. TABLE/LIST/TASK 指定查询的方式
dataview 现支持以下3中查询方式:
1. **TABLE**:表格视图,可以输出一个页面的多个该页面的字段值,后面可跟多个 field 并输出字段值。
下面的例子以表格的形式输出文件的标签和创建时间:
```sql
```dataview
table file.tags as 标签,file.ctime
limit 100
```
```
1. **LIST**:列表视图,每个页面只能输出一个该页面的字段值,或者使用加号输出多个字段值(不建议)。
下面的例子输出文件的标签加文件创建时间:
```sql
```dataview
list file.tags + file.ctime
limit 100
```
```
1. **TASK**:任务视图。
下面的例子用于展示5个有任务的文档的任务:
```sql
```dataview
task
where file.tasks
limit 5
```
```
### 2. FROM 查询的文档源
指定查询源,即文档的初步筛选,详见 [source](#1. source 源)。
### 3. WHERE 条件筛选
根据字段筛选页面,只有表达式结果为 `true` 的页面才会被输出。
```
WHERE <clause>
```
1. 获取最近24h内修改过的页面:
```
LIST WHERE file.mtime >= date(today) - dur(1 day)
```
1. 获取未完成并且创建时间距今1个月的项目:
```
LIST FROM #projects
WHERE !completed AND file.ctime <= date(today) - dur(1 month)
```
### 4. SORT 排序
按一个或多个字段对所有结果进行排序。
```
SORT date [ASCENDING/DESCENDING/ASC/DESC]
```
您还可以提供多个字段进行排序。将根据第一个字段进行排序。然后,如果出现平局,第二个字段将用于对平局字段进行排序。如果仍然存在平局,则第三类将解决它,依此类推。
```
SORT field1 [ASCENDING/DESCENDING/ASC/DESC], ..., fieldN [ASC/DESC]
```
### 5. GROUP BY 分组
将所有结果分组到一个字段上。为每个唯一字段值生成一行,该字段有两个属性:一个对应于要分组的字段,另一个是 `rows` 多行数组字段,其中包含匹配的所有页面。
```
GROUP BY field
GROUP BY (computed_field) AS name
```
为了使用 `rows` 多行数组更容易,Dataview 支持字段 “swizzling”。如果要从 `rows` 多行数组中的每个对象获取字段 `test`,则 `rows.test` 将自动从 `rows` 多行数组中的每个对象获取 `test` 字段,从而生成一个新数组。然后可以对结果数组应用聚合运算符,如 `sum()`。
例如,使用以下代码可以依照标签分组并输出文件名称:
```sql
```dataview
table rows.file.name as 文件名称
where file.tags
group by file.tags
```
```
### 6. FLATTEN 扁平化
展平每行中的数组,在数组中的每个条目中生成一个结果行。(不会用,总是报错)
```sql
FLATTEN field
FLATTEN (computed_field) AS name
```
### 7. LIMIT 输出结果数目限制
限制输出结果的数目。
下面的例子输出2个结果:
```sql
```dataview
table file
limit 2
```
```
## 关键字后面的内容
介绍 dataview 查询格式中关键字后面的内容怎么填。
```sql
```dataview
TABLE|LIST|TASK <field> (AS "Column Name"), <field>, ..., <field>
FROM <source>
WHERE <expression>
SORT <expression> (ASC/DESC)
... other data commands
```
```
### 1. source 源
- **标签**:选择一个标签, `FROM #tag`.
- **文件夹**:选择一个文件夹, `FROM "folder"`.
- **链接文件**:选择链接到某文档的文档,或被某文档所链接的文档:
- 链接到某文档的文档,`FROM [[note]]`.
- 某文档链接的文档, `FROM outgoing([[note]])`.
- 上面的源也可以使用 `and` 和 `or` 组合起来进行使用,举例说明:
- `#tag and "folder"` 会返回所有在 `folder` 文件夹下且带有 `#tag` 标签的文档。
- `[[Food]] or [[Exercise]]` 会返回任何链接到 `[[Food]]` 或 `[[Exercise]]` 的文件。
### 2. field 字段
- 内置字段:
- 想查看 file 有哪些属性?可以使用下列代码来进行查看
```sql
```dataview
table file
limit 1
```
```
- 自定义字段:
- 在文档中以 `字段名1::值1` 的格式创建新的字段值
### 3. expression 表达式
```sql
# 一般操作
field (直接指向一个field)
simple-field (指向带有空格或标点的fields,例如"Simple Field!")
a.b (如果 a 是一个对象,返回其字段'b'的值)
a[expr] (如果 a 是一个对象或者数组,返回带有名称为 'expr' 的 field)
f(a, b, ...) (调用名为 `f` 的函数并输入参数:a, b, ...)
# 数学运算
a + b (加法)
a - b (减法)
a * b (乘法)
a / b (除法)
# 比较
a > b (检查 a 是否大于 b)
a < b (检查 a 是否小于 b)
a = b (检查 a 是否等于 b)
a != b (检查 a 是否不等于 b)
a <= b (检查 a 是否小于等于 b)
a >= b (检查 a 是否大于等于 b)
# 特殊操作
[[Link]].value (从页面 `Link` 获取 `value` 的值)
```
上述表达式的详细信息见下方。
#### fields 字段名
- 最简单的就是直接指向"字段名"。
- 例如你在某个文档内有一个字段名叫 "field",那么你就可以直接指向字段的名字 `field` 以获得拥有该字段名的文档。
- 如果"字段名"中包含空格、标点符号或者其它的非字母或数字的字符,那么你就可以使用 Dataview 的简化名称,它会将所有字母小写,并将空格替换为"-"。例如:
- 使用 `this-is-a-field` 可以获得字段名诸如 `this is a field` 、`THIS is a FIELD` 等的文档
- 使用 `hello` 可以获得拥有字段名诸如 `Hello!` 等的文档。(经测试无效)
#### 数学运算
可以使用标准运算符组合字段:加(`+`),减(`-`),乘 (`*`),除 (`/`)。例如 `field1 + field2` 是一个求取字段和的表达式。
#### 比较
您可以使用各种比较运算符来比较大多数值:`<`、`>`、`<=`、`>=`、`=`、`=`、`!=`。这将产生一个布尔真值(true)或假值(false)。
#### 数组/对象索引
您可以通过索引操作符 `array[<index>]` 从**数组**中检索数据,其中 `<index>` 是**任何计算表达式**。数组的第一个元素的索引是0,第二个元素是索引1,依此类推。例如列表 `(1,2,3)[0]=1`。
还可以使用索引操作符从**对象**(将文本映射到数据值)检索数据,其中索引现在是**字符串/文本,而不是数字**。您还可以使用缩写 `object.<name>`,其中 `<name>` 是要检索的值的名称。例如 `object("yes", 1).yes=1`。
#### 函数调用
Dataview支持各种用于操作数据的函数,这些函数在 [functions documentation](https://blacksmithgu.github.io/obsidian-dataview/query/expressions/functions) 中有详细描述。
它们具有一般语法`function(arg1, arg2, ...)`,例如:`lower("yes")` 或者 `regexmatch("text", ".+")`。
具体函数详见 [function 函数](#function 函数)。
#### 特殊类型及其值
大多数 dataview 类型都与运算符有特殊的交互,或者可以通过索引运算符来检索附加字段。
##### Dates 日期
您可以通过以下方式检索日期的各个部分:`date.year`、`date.month`、`date.day`、`date.hour`、`date.minute`、`date.second`、`date.week`。您还可以向日期添加持续时间以获取新日期。
使用举例:
```
```dataview
TABLE file.ctime.year as "这是文件创建日期的年份"
LIMIT 1
```
```
##### Durations 周期
持续时间可以相互添加,也可以添加到日期。您可以通过索引检索持续时间的各个组成部分:`duration.years`、`duration.months`、`duration.days`、`duration.hours`、`duration.minutes`、`duration.seconds`。
##### Links 链接
您可以通过“索引”链接来获取相应页面上的值。例如 `[[Link]].value` 将从页面链接获取值。
## function 函数
大多数函数既可以应用于单个值(如数字、字符串、日期等),也可以应用于这些值的列表。如果将函数应用于列表,则在将函数应用于列表中的每个元素后,它也会返回一个列表。例如:
```sql
lower("YES") = "yes"
lower(list("YES", "NO")) = list("yes", "no")
replace("yes", "e", "a") = "yas"
replace(list("yes", "ree"), "e", "a") = list("yas", "raa")
```
### Constructors 构造函数
构造器用于创建值。
#### `object(key1, value1, ...)` 对象构造器
Creates a new object with the given keys and values. Keys and values should alternate in the call, and keys should always be strings/text.
```
object() => empty object
object("a", 6) => object which maps "a" to 6
object("a", 4, "c", "yes") => object which maps a to 4, and c to "yes"
```
#### `list(value1, value2, ...)` 列表构造器
创造一个新列表并为其赋值。
```
list() => empty list
list(1, 2, 3) => list with 1, 2, and 3
list("a", "b", "c") => list with "a", "b", and "c"
```
#### `date(any)` 日期构造器
解析字符串、日期或者链接的对象以获取日期。
```
date("2020-04-18") = <date object representing April 18th, 2020>
date(today) = <date object 今天的日期>
date([[2021-04-16]]) = <date object for the given page, refering to file.day>
```
#### `dur()` 周期构造器
未找到说明
```
dur(1 day) = 1天的周期
```
#### `number(string)` 数字构造器
Pulls the first number out of the given string, returning it if possible. Returns null if there are no numbers in the string.
```
number("18 years") = 18
number(34) = 34
number("hmm") = null
```
#### `link(path, [display])` 链接
根据参数中的path路径构造一个链接对象。如果输入display参数,则该链接显示名称为display。
```
link("Hello") => link to page named 'Hello'
link("Hello", "Goodbye") => link to page named 'Hello', displays as 'Goodbye'
```
#### `elink(url, [display])` 外部链接
构造一个外部链接(例如 `www.google.com`)。如果输入display参数,则该外链显示名称为display。
```
elink("www.google.com") => link element to google.com
elink("www.google.com", "Google") => link element to google.com, displays as "Google"
```
### Numeric Operations 数字操作函数
#### `round(number, [digits])`
将数字四舍五入到给定的位数。如果未指定第二个参数,则四舍五入到最接近的整数;否则,四舍五入到给定的位数。
```
round(16.555555) = 7
round(16.555555, 2) = 16.56
```
### Objects, Arrays, and String Operations 对象、数组、字符串操作
操作对象内部的值。
#### `contains(object|list|string, value)` 是否包含某值?
检查给定的容器类型中是否包含给定的值。根据第一个参数是对象、列表还是字符串,此函数的行为略有不同。
- 对于对象,检查对象是否具有具有给定名称的键。例如:
```
contains(file, "ctime") = true
contains(file, "day") = true (if file has a date in its title, false otherwise)
```
- 对于列表,检查是否有任何数组元素等于给定值。例如:
```
contains(list(1, 2, 3), 3) = true
contains(list(), 1) = false
```
- 对于字符串,检查给定值是否为字符串的子字符串。例如:
```
contains("hello", "lo") = true
contains("yes", "no") = false
```
#### `extract(object, key1, key2, ...)` 提取对象中的键值
从对象中提取多个字段,然后可以使用这些字段创建新对象。例如:
```
extract(file, "ctime", "mtime") = object("ctime", file.ctime, "mtime", file.mtime)
extract(object("test", 1)) = object()
```
#### `sort(list)` 列表排序
对列表排序并返回新列表。
```
sort(list(3, 2, 1)) = list(1, 2, 3)
sort(list("a", "b", "aa")) = list("a", "aa", "b")
```
#### `reverse(list)` 反转列表
反转列表,按相反顺序返回新列表。
```
reverse(list(1, 2, 3)) = list(3, 2, 1)
reverse(list("a", "b", "c")) = list("c", "b", "a")
```
#### `length(object|array)` 长度
返回对象中的字段数或数组中的条目数。
```
length(list()) = 0
length(list(1, 2, 3)) = 3
length(object("hello", 1, "goodbye", 2)) = 2
```
#### `sum(array)` 数组求和
对数组中的所有数值求和。
```
sum(list(1, 2, 3)) = 6
```
#### `all(array)` 数组值均为真?
仅当数组中的所有值均为truthy时,才返回 `true`。您还可以将多个参数传递给此函数,在这种情况下,只有当所有参数都为truthy时,它才会返回 `true`。
```
all(list(1, 2, 3)) = true
all(list(true, false)) = false
all(true, false) = false
all(true, true, true) = true
```
#### `any(array)` 数组值存在真?
如果数组中的任何值为truthy,则返回 `true`。您还可以将多个参数传递给此函数,在这种情况下,如果任何参数为truthy,它将返回 `true`。
```
any(list(1, 2, 3)) = true
any(list(true, false)) = true
any(list(false, false, false)) = false
all(true, false) = true
all(false, false) = false
```
#### `none(array)` 数组值均为假?
如果数组中的值都不是真的,则返回 `true`。
#### `join(array)` 数组拼接成字符串
将数组中的元素合并为单个字符串。如果提供了第二个参数,则每个元素将由给定的分隔符(即第二个参数)分隔。
```
join(list(1, 2, 3)) = "1, 2, 3"
join(list(1, 2, 3), " ") = "1 2 3"
join(6) = "6"
join(list()) = ""
```
### String Operations 字符串操作
#### `regexmatch(pattern, string)` 正则匹配
检查给定字符串是否与给定模式匹配(使用JavaScript正则表达式引擎)。
```
regexmatch("\w+", "hello") = true
regexmatch(".", "a") = true
regexmatch("yes|no", "maybe") = false
```
#### `regexreplace(string, pattern, replacement)` 正则替换
将 `string` 中正则匹配式 `pattern` 匹配的所有实例替换为 `replacement`。
这里使用JavaScript替换方法,因此您可以使用诸如 `$1` 之类的特殊字符来引用第一个匹配的字符串(`$2` 就是第二个匹配的字符串),等等。
```
regexreplace("yes", "[ys]", "a") = "aea"
regexreplace("Suite 1000", "\d+", "-") = "Suite -"
```
#### `replace(string, pattern, replacement)` 替换
将 `string` 中 `pattern` 匹配的所有字符串替换为 `replacement`。
```
replace("what", "wh", "h") = "hat"
replace("The big dog chased the big cat.", "big", "small") = "The small dog chased the small cat."
replace("test", "test", "no") = "no"
```
#### `lower(string)` 转小写
将字符串转换为全小写。
```
lower("Test") = "test"
lower("TEST") = "test"
```
#### `upper(string)` 转大写
将字符串转换为全大写。
```
upper("Test") = "TEST"
upper("test") = "TEST"
```
### Utility Functions 实用功能函数
#### `default(field, value)` 字段默认值
如果 `field` 为空,则返回 `value`;否则返回 `field` 的值。
用于用默认值替换空值。例如,要显示尚未完成的项目,使用 `incomplete`作为其默认值:
```
default(dateCompleted, "incomplete")
```
默认值的两个参数中都是矢量化的;如果需要使用列表参数上的默认值,即不对列表的空值做出改变,就使用 `ldefault`,它与 `default` 相同,但不是矢量化的。
```
default(list(1, 2, null), 3) = list(1, 2, 3)
ldefault(list(1, 2, null), 3) = list(1, 2, null)
```
#### `choice(bool, left, right)` 判断输出语句
如果第一个参数为真,则返回 `left`;否则返回 `right`。
```
choice(true, "yes", "no") = "yes"
choice(false, "yes", "no") = "no"
choice(x > 4, y, z) = y if x > 4, else z
```
#### `striptime(date)`
去掉日期的时间部分,只留下年、月和日。如果你不在乎具体时间的话,就可以用它来比较日期。
```
striptime(file.ctime) = file.cday
striptime(file.mtime) = file.mday
```
# dataviewjs
Dataview JavaScript API允许通过访问Dataview的索引和查询引擎以执行任意JavaScript,这有利于复杂视图或与其他插件的互操作。
## 概览
```js
```dataviewjs
<code>
```
```
在这些代码块中执行的代码可以访问 `dv` 变量,该变量提供了与代码块相关的dataview API的全部内容(如 `dv.table()`、`dv.pages()` 等)。更多信息见[代码块参考](#代码块参考)。
## DataArray 数据数组
Dataview中的结果列表的一般抽象成 `DataArray`,它是一个具有附加功能的代理数组。
数据数组支持索引和迭代(通过 `for` 和 `for ... of` 来遍历数组中的项目),还包括许多数据操作符,如 `sort`,`groupBy`,`distinct`,`where` 等,这使得表格数据的维护变得简单。
### 创建 DataArray
`DataArray` 由大多数Dataview API返回,并可以返回多个结果,例如 `dv.pages()` 返回所有的文档数据数组。
### DataArray 与普通数组的转换
您还可以使用 `dv.array(<array>)` 将普通JavaScript 数组显式转换为Dataview数组。
如果要将数据数组转换回普通数组,请使用 `DataArray#array()`。
### DataArray 索引
数据数组支持常规索引,就像普通数组一样(比如 `array[0]`)。
但重要的是,它们还支持查询语言风格的“swizzling”:如果使用字段名(比如 `array.field`)对数据数组进行索引,它会自动将数组中的每个元素映射到 `field`,如果 `array.field` 对应的值本身也是一个数组,则会将 `field` 变平。
例如,`dv.pages().file.name` 将返回库中所有文件名的数据数组。`dv.pages(“#books”).genres`将返回书籍中所有类型的扁平列表。
### DataArray 原始接口
下面提供了 `DataArray` 实现的完整的接口以供参考:
```js
/** A function which maps an array element to some value. */
export type ArrayFunc<T, O> = (elem: T, index: number, arr: T[]) => O;
/** A function which compares two types (plus their indices, if relevant). */
export type ArrayComparator<T> = (a: T, b: T) => number;
/**
* Proxied interface which allows manipulating array-based data. All functions on a data array produce a NEW array
* (i.e., the arrays are immutable).
*/
export interface DataArray<T> {
/** The total number of elements in the array. */
length: number;
/** Filter the data array down to just elements which match the given predicate. */
where(predicate: ArrayFunc<T, boolean>): DataArray<T>;
/** Alias for 'where' for people who want array semantics. */
filter(predicate: ArrayFunc<T, boolean>): DataArray<T>;
/** Map elements in the data array by applying a function to each. */
map<U>(f: ArrayFunc<T, U>): DataArray<U>;
/** Map elements in the data array by applying a function to each, then flatten the results to produce a new array. */
flatMap<U>(f: ArrayFunc<T, U[]>): DataArray<U>;
/** Mutably change each value in the array, returning the same array which you can further chain off of. */
mutate(f: ArrayFunc<T, any>): DataArray<any>;
/** Limit the total number of entries in the array to the given value. */
limit(count: number): DataArray<T>;
/**
* Take a slice of the array. If `start` is undefined, it is assumed to be 0; if `end` is undefined, it is assumbed
* to be the end of the array.
*/
slice(start?: number, end?: number): DataArray<T>;
/** Concatenate the values in this data array with those of another data array. */
concat(other: DataArray<T>): DataArray<T>;
/** Return the first index of the given (optionally starting the search) */
indexOf(element: T, fromIndex?: number): number;
/** Return the first element that satisfies the given predicate. */
find(pred: ArrayFunc<T, boolean>): T | undefined;
/** Find the index of the first element that satisfies the given predicate. Returns -1 if nothing was found. */
findIndex(pred: ArrayFunc<T, boolean>): number;
/** Returns true if the array contains the given element, and false otherwise. */
includes(element: T): boolean;
/**
* Return a sorted array sorted by the given key; an optional comparator can be provided, which will
* be used to compare the keys in leiu of the default dataview comparator.
*/
sort<U>(key: ArrayFunc<T, U>, direction?: 'asc' | 'desc', comparator?: ArrayComparator<U>): DataArray<T>;
/**
* Return an array where elements are grouped by the given key; the resulting array will have objects of the form
* { key: <key value>, rows: DataArray }.
*/
groupBy<U>(key: ArrayFunc<T, U>, comparator?: ArrayComparator<U>): DataArray<{ key: U, rows: DataArray<T> }>;
/**
* Return distinct entries. If a key is provided, then rows with distinct keys are returned.
*/
distinct<U>(key?: ArrayFunc<T, U>, comparator?: ArrayComparator<U>): DataArray<T>;
/** Return true if the predicate is true for all values. */
every(f: ArrayFunc<T, boolean>): boolean;
/** Return true if the predicate is true for at least one value. */
some(f: ArrayFunc<T, boolean>): boolean;
/** Return true if the predicate is FALSE for all values. */
none(f: ArrayFunc<T, boolean>): boolean;
/** Return the first element in the data array. Returns undefined if the array is empty. */
first(): T;
/** Return the last element in the data array. Returns undefined if the array is empty. */
last(): T;
/** Map every element in this data array to the given key, and then flatten it.*/
to(key: string): DataArray<any>;
/**
* Recursively expand the given key, flattening a tree structure based on the key into a flat array. Useful for handling
* heirarchical data like tasks with 'subtasks'.
*/
expand(key: string): DataArray<any>;
/** Run a lambda on each element in the array. */
forEach(f: ArrayFunc<T, void>): void;
/** Convert this to a plain javascript array. */
array(): T[];
/** Allow iterating directly over the array. */
[Symbol.iterator](): Iterator<T>;
/** Map indexes to values. */
[index: number]: any;
/** Automatic flattening of fields. */
[field: string]: any;
}
```
## 代码块参考
### 查询
#### `dv.current()` 当前页面
得到当前页面(脚本运行的页面)的信息。
#### `dv.pages(source)` 指定源的页面
此处的 `source` 同 dataview 中的一样,详见 [source](#1. source 源)。
```
dv.pages("#books") => all pages with tag 'books'
dv.pages('"folder"') => all pages from folder "folder"
dv.pages("#yes or -#no") => all pages with tag #yes, or which DON'T have tag #no
```
#### `dv.pagePaths(source)` 指定源的页面的路径
```
dv.pagePaths("#books") => the paths of pages with tag 'books'
```
#### `dv.page(path)` 指定路径的页面
将简单路径映射到包含所有页面字段的完整页面对象。自动执行链接解析,如果不存在,将自动补充扩展名。
```
dv.page("Index") => The page object for /Index
dv.page("books/The Raisin.md") => The page object for /books/The Raisin.md
```
### 渲染
#### `dv.header(level, text)` 渲染标题
使用所给的文本渲染 1~6 级标题。
```
dv.header(1, "Big!");
dv.header(6, "Tiny");
```
#### `dv.paragraph(text)` 渲染文本
在段落中呈现任意文本。
```
dv.paragraph("This is some text");
```
### 数据展示
#### `dv.list(elements)` 列表视图
呈现元素的dataview列表。参数允许普通数组和数据数组。
```
dv.list([1, 2, 3]) => list of 1, 2, 3
dv.list(dv.pages().file.name) => list of all file names
dv.list(dv.pages().file.link) => list of all file links
dv.list(dv.pages("#book").where(p => p.rating > 7)) => list of all books with rating greater than 7
```
#### `dv.taskList(tasks, groupByFile)` 任务视图
呈现由 `page.file.tasks` 获得的“Task”对象的dataview列表。只需要第一个参数;如果提供了第二个参数“groupByFile”(且为true),则任务将根据它们来自的文件自动分组。
```
// List all tasks from pages marked '#project'
dv.taskList(
dv.pages("#project").file.tasks
)
// List all *uncompleted* tasks from pages marked #project
dv.taskList(
dv.pages("#project").file.tasks
.where(t => !t.completed)
)
// List all tasks tagged with '#tag' from pages marked #project
dv.taskList(
dv.pages("#project").file.tasks
.where(t => t.text.includes("#tag")) // 这里的 t 指代的是 dv.pages("#project").file.tasks 中的每个项目,在这里即为任务对象
)
```
#### `dv.table(headers, elements)` 表格视图
使用给定的表头列表和二维元素数组呈现dataview表。
```
// Render a simple table of book info sorted by rating.
dv.table(
["File", "Genre", "Time Read", "Rating"],
dv.pages("#book")
.sort(b => b.rating) // 这里的 b 指代的是 dv.pages("#book") 中的每个项目,在这里即为文件对象
.map(b => [b.file.link, b.genre, b["time-read"], b.rating]))
```
### 实用功能函数
#### `dv.array(value)` 普通数组转数据数组
在[DataArray中的转换](#DataArray 与普通数组的转换)中介绍过。
```
dv.array([1, 2, 3]) => dataview data array [1, 2, 3]
```
#### `dv.compare(a, b)` 比较
根据dataview的默认比较规则比较两个任意JavaScript值;如果您正在编写自定义比较器并希望返回默认行为,则此选项非常有用。如果 `a<b`,则返回负值;如果 `a=b`,则返回0;如果 `a>b`,则返回正值。
```
dv.compare(1, 2) = -1
dv.compare("yes", "no") = 1
dv.compare({ what: 0 }, { what: 0 }) = 0
```
#### `dv.equal(a, b)` 相等?
根据Dataview的默认比较规则,比较两个任意JavaScript值,如果它们相等,则返回true。
```
dv.equal(1, 2) = false
dv.equal(1, 1) = true
```
## JS 的代码调试方法
可以使用 `alert()` 输出想要的信息(不推荐);
也可以打开控制台:<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>i</kbd> ,然后使用 `console.log()` 输出信息到控制台(**推荐**)。
想看 `DataArray` 类型的文件都含有什么属性?使用以下代码即可在控制台查看其属性,然后调用就可以了:
```sql
```dataviewjs
console.log("这是 file 的属性");
console.log(dv.current().file);
console.log("这是 file.tasks 的属性");
console.log(dv.current().file.tasks);
```
```
## 例子
都是自用的例子,只是能用的级别。
我的文件存放方式大致如下:
- `根目录`
- `主 moc.md`(这个用来索引资源、项目的 moc 文件)
- `项目`(项目文件夹)
- `水质检测项目`(这个是一个项目文件夹)
- `水质检测项目.md`(这个是和文件夹相同名称的文档,也是该文件夹下所有文件的索引,即 moc)
- `文档1.md`
- `文档2.md`
- ……
- ……
- `资源`(资源文件夹)
- `markdown`(这个是一个资源文件夹)
- `markdown.md`(这个是和文件夹相同名称的文档,也是该文件夹下所有文件的索引,即 moc)
- `文档1.md`
- `文档2.md`
- ……
- ……
下面结合我的文件存放方式说几个例子。
### 示例一:获取当前文件所在文件夹下所有文件的任务并计算总进度
该代码块可以放入某个项目或者资源文件夹中的moc文件,用于总览该项目或资源的任务进度。当然你也可以将代码放入该文件夹下的其他文件,这就看个人需求了,重点是看懂代码。
例如将代码放入下图所示的 `水质检测项目.md` 文件中:
![image-20210816104300278](assets/image-20210816104300278.png)
```sql
```dataviewjs
// 计算任务进度
var allTask = 0; //用于计算任务总数
var completedTask = 0; //用于计算文件完成数目
for(var task of dv.pages().file.tasks.where(t => t.path.match(dv.current().file.folder))){
if(task.completed){
completedTask++;
}
allTask++;
}
// 展示任务进度
if(allTask){
dv.paragraph('任务完成进度:**' + (completedTask/allTask * 100).toFixed(1) + '%**')
}
// 获取并展示当前文件夹下所有文件的任务
dv.taskList(
dv.pages().file.tasks
.where(t => t.path.match(dv.current().file.folder))
.sort(t => t.ctime)
)
```
```
### 示例二:获取当前文件所在文件夹下未被本文档链接的文档
我的文件存储方式是某个项目或资源的文件夹中的 moc 文档会使用 `[[文档名]]` 来链接其它文档,例如:
```markdown
这是 markdown.md 文件
markdown 使用很方便,可以通过 [[简介]] 了解,然后通过 [[快速上手]] 进行学习。
```
上面的这个资源文件 moc 只引用其文件夹下的 2 个文档,有时一个资源文件夹下有很多文档,有的可能并未被链接,我们也很难发现,这时使用下列代码来实现获取当前文件夹下未被本文档链接的文档。
```sql
```dataviewjs
// 初步筛选,筛选2次,先获得当前文件夹下的文档,再去除当前文档
var currentFolderFilesExceptThis = dv.pages().file
.where(b => b.path.indexOf(dv.current().file.folder)!=-1)
.where(b => b.path!=dv.current().file.path);
// 进一步筛选,获取未被当前文档链接的文档
var pages = new Array(); //创建新数组用于存放未被链接的文件
var linked;
for(var file of currentFolderFilesExceptThis){
linked = 0;
for(var outlink of dv.current().file.outlinks){
if(outlink.path==file.path){
linked = 1;
break;
}
}
if(!linked){
pages.push(file)
}
}
// 将普通数组转换为DataArray类型
dv.list(dv.array(pages).link);
```
```
### 示例三:获取某目录下资源或项目文件夹的 moc 文档链接、标签和任务进度
这个文件放在 `主 moc.md` 中,它可以某目录下资源或项目文件夹的 moc 文档链接、标签和任务进度。
下方是获取资源文件夹中的资源文件的 moc 文档链接、标签和任务进度:
```sql
```dataviewjs
// 写入 moc文件所在文件夹的父文件夹的路径
const Path = "资源/"; // x
// 获取指定目录下各文件夹中的 moc 文件
var mocFiles = dv.pages().file
.where(b => b.path.indexOf(Path)!=-1)
.where(b => b.path.endsWith(b.name + '/' + b.name + '.md'))
// 处理 moc 文件的标签、任务进度
for(var mocFile of mocFiles){
// 处理标签:获取该 moc 所在文件夹下的所有标签(无重复显示标签)
var allTags = new Array();
for(var file of dv.pages().file.where(b => b.path.match(mocFile.folder))){
for(var tag of file.tags){
if(allTags.indexOf(tag)==-1){
allTags.push(tag)
}
}
}
mocFile["myTags"] = '';
for(var tag of allTags){
mocFile["myTags"] = mocFile["myTags"] + tag + ' ';
}
// 处理任务进度:获取该 moc 文件所在文件夹下所有的任务并计算任务进度
var allTask = 0;
var completedTask = 0;
for(var task of dv.pages().file.tasks.where(t => t.path.match(mocFile.folder))){
if(task.completed){
completedTask++;
}
allTask++;
}
if(allTask){
mocFile["jindu"] = '任务完成进度:**' + (completedTask/allTask * 100).toFixed(1) + '%**';
}
}
// 展示成表格的形式
dv.table(
['文件', '标签', '任务'],
mocFiles
.map(b => [b.link, b.myTags, b.jindu])
)
```
```