Obsidian&Zettelkasten&LYT構(gòu)建第二大腦系列文章總目錄(持續(xù)更新)
? ? ? 我們接著上一篇,Step1-先預(yù)熱:一文講透Obsidian插件DataviewJS苔咪,繼續(xù)講解第二步:知其然乏屯。作為熱身,我們還是先看一段相對簡單一點的代碼:
? ? ? 這段代碼的運行結(jié)果是:在筆記庫vault中病梢,把標簽為“book”的筆記找出來胃珍,然后按照書籍的類型進行分組,每組用一個表格的形式展示出來蜓陌,表格的表頭包含“姓名name”觅彰、“閱讀時間TimeRead”、“評分Rating”护奈,幾個字段缔莲,表格的內(nèi)容按照書籍評分降序排列。執(zhí)行效果如下:
? ? ? 分析代碼霉旗,格式排版很重要痴奏,我的習(xí)慣是把他們放到代碼編輯器里進行排版,這樣便于自己閱讀和理解厌秒,這里選用Sublime Text來編寫和閱讀代碼读拆。具體怎么用,后面找機會單獨介紹鸵闪,排版以后的代碼如下:
? ? ? 這么看順眼多了檐晕,也更好理解。整段代碼是嵌入在obsidian筆記中的,使用“```davaviewjs”做開頭,使用“```”做結(jié)尾辟灰,里面放的是javascript代碼个榕,準確的說應(yīng)該是typerscript代碼。因為Dataview的作者使用的typerscript來開發(fā)的Dataview插件芥喇。這個從github上的項目文件后綴就可以看出來西采,都是以*.ts結(jié)尾的。
? ? ? 代碼源文件src下面包括多個目錄继控,隨便打開一個里面的文件都是以*.ts結(jié)尾械馆。這里api和data兩個目錄,后面我們會重點介紹里面幾個關(guān)鍵的源代碼文件武通∨椋看源代碼可以在瀏覽器的github里打開直接看,不過我強烈建議把整個源碼下載到本地冶忱,然后用Sublime Text導(dǎo)入整個項目尾菇,借助代碼編輯器讀源代碼的效果會高出數(shù)倍。
? ? ? ?? 首先是一個for語句朗和,在typerscript的for循環(huán)語句有兩種形式错沽,這里采用的是常用的for...of語法。意思就是在一個集合中逐一取出一個元素進行遍歷眶拉,針對取出的這個元素千埃,做一些處理動作。for循環(huán)體()里的部分是對遍歷的集合做一個條件限制忆植。
? ? ? ?? let 是一個定義變量的關(guān)鍵詞放可,類似javascript里面的var,不過let的用法更靈活朝刊,它可以定義任意類型的變量耀里,比如
?let aaa : string = "hello"
這里就定義了一個string字符串類型的變量叫aaa。還可以定義別的拾氓,比如
?let dance = function(name : string) {return "Look! ${name} is dancing!"}
這里let就定義了一個函數(shù)變量dance冯挎,這個函數(shù)定義用到了function關(guān)鍵詞,在()里定義了一個需要輸入的參數(shù)name咙鞍,而且明確name的類型為string字符串房官,在{}里定義了函數(shù)要做的動作,return是關(guān)鍵詞续滋,表示整個函數(shù)運行完后返回的結(jié)果翰守。這里函數(shù)返回的是一個字符串,一句話:XXX在跳舞疲酌,這里的XXX因為在""內(nèi)蜡峰,所以使用了簡寫的方式了袁,使用${}的方式直接調(diào)用了參數(shù)name的值,比如函數(shù)是dance("Jack")湿颅,那么結(jié)果輸出就是:"Look! Jack is dancing!""载绿。當然typerscript在定義函數(shù)時有好幾種不同的方式,比如剛才的定義也可以寫成:
?let dance => (name : string): "Look! ${name} is dancing!"
看上去是不是簡潔了很多油航,這是使用=>定義函數(shù)的方式卢鹦,在typescript的代碼里十分常見,要習(xí)慣劝堪。其實,typerscript和JavaScript相比揉稚,代碼定義更嚴格秒啦,它是對JavaScript的擴充,針對泛型的使用更高頻搀玖,代碼更簡潔余境,但有時候過度簡潔讀起來不是特別好理解。比如還是這句灌诅,如果用泛型來定義可以寫成:
?let dance<T> => (args : T) : T
這里使用泛型<T>的好處就是可以不用事先確定參數(shù)的類型和返回的類型芳来,函數(shù)的適用范圍更靈活,后面我們講解dataviewAPI的部分源碼時會經(jīng)常碰到這樣的情況猜拾。一般我們寫程序即舌,比如java等,編程的過程都是針對值進行編程挎袜,typerscript前進了一步顽聂,它能夠針對類型進行編程。比如還是這個例子盯仪,我們可以定義一個自定義的新類型danceType紊搪,讓它把這種函數(shù)形態(tài)給記錄下來以后隨時使用:
?type danceType<T> = (args : T) => T
type是一個關(guān)鍵詞,可以理解為給一個自定義的數(shù)據(jù)類型起了一個別名全景,這個就是給一個自定義的函數(shù)類型的一個數(shù)據(jù)類型耀石,起了個別名叫danceType“只疲或者舉個簡單的例子:
?type mystr = string
就是給string類型另外起了一個別名叫mystr滞伟,實際上還是同一個類型。要義就是通過這種方式對類型進行編程了馆纳。結(jié)合上泛型诗良,就變得十分靈活,不過可讀性也確實燒腦了鲁驶。讀源碼的時候這種類型+泛型的代碼很多鉴裹,需要熟悉和習(xí)慣。后面我會留一些配套的文章,供大家慢慢學(xué)習(xí)熟悉径荔。
? ? ? ?? 繼續(xù)看例子:for的()里的意思督禽,使用let定義了一個group變量,因為group放在了for...of中間总处,所以group就是of后面跟著的那個集合中取出的一組元素狈惫,確切的說就是
?dv.pages("#book").groupBy(p => p.genre)?
所代表的一組元素集合,是一個數(shù)據(jù)結(jié)構(gòu)鹦马。這里要弄清含義胧谈,就需要看看github上作者給出的DataviewAPI了,里面給出了常用的一些函數(shù)的說明荸频,位置在首頁的概述部分:
打開后菱肖,可以看到一些常用的函數(shù):
我的英文不好,所以經(jīng)常是用翻譯軟件旭从,中英文來回切換著看稳强,這樣效率更高一些。
? ? ? 從API文檔里可以看到和悦,dv是在obsidian筆記中調(diào)用Dataview的一個代名詞退疫,一般的函數(shù)都是從dv.XXX開始的。dv.pages(source)鸽素,這個函數(shù)可以根據(jù)傳入?yún)?shù)source的不同返回符合參數(shù)條件的筆記集合褒繁,主要支持兩種方式:按標簽和按筆記所在的目錄或者路徑,這些條件可以通過與或非進行條件組合馍忽。從作者給的例子里可以看出函數(shù)返回的是一個筆記的集合pages澜汤,里面會有一篇一篇的筆記page。實際上從這個API文檔中我們得到的確切信息不足舵匾,比如返回的結(jié)果到底是什么類型俊抵,看不出來,只能猜出大概的意思是一個筆記的集合坐梯,但是具體的數(shù)據(jù)類型并不清楚徽诲,這種不清晰會給我們后續(xù)理解代碼帶來很大的障礙,編程不是感覺怎么怎么樣吵血,而且確切的推理和推導(dǎo)過程谎替,計算機代碼是嚴絲合縫的,不是靠猜的蹋辅。要想做到這點钱贯,就需要更進一步追蹤進去看源代碼了,這個我們放到后面第三步再說侦另,這里先意會吧秩命。其他函數(shù)的意思大家自己去看API尉共,不再逐個做解釋。
? ? ? typescript支持函數(shù)嵌套的寫法弃锐,前一個函數(shù)返回的對象可以繼續(xù)調(diào)用他所支持的函數(shù)繼續(xù)一層層調(diào)用下去袄友,所以會出現(xiàn)很多個函數(shù).函數(shù).函數(shù)這樣一直連續(xù)調(diào)用一長段,很正常霹菊,習(xí)慣就好剧蚣。在這里dv.pages()函數(shù)返回筆記頁面構(gòu)成的集合對象后,繼續(xù)調(diào)用了一個groupBy函數(shù)進行分組旋廷,groupBy()內(nèi)部的寫法是一個典型的泛型參數(shù)傳參的寫法鸠按,這個后面我們看源代碼的時候在繼續(xù)深究,這里只需要明白饶碘,groupBy()函數(shù)是將前面的筆記集合中的元素待诅,用genre分類屬性作為對筆記集合的分組條件,這樣返回的結(jié)果就是按照分類把書籍分成了幾組熊镣,所以for循環(huán)的次數(shù),和分組后的組數(shù)是一致的募书,看一眼for循環(huán)體內(nèi)的句子绪囱,我們大概能猜到,每組書籍應(yīng)該是以表格形式來呈現(xiàn)的莹捡,有幾組就有幾張表格鬼吵。
? ? ? ?? for循環(huán)體內(nèi)的語句,不展開篮赢,使用了dv.head()與dv.table()的方式來輸出三級標題和畫表格齿椅。這里需要重點提兩個地方:
? ? ? 第一是group.key的用法。group在前面提了启泣,是每次for循環(huán)從筆記集合體遍歷出來的一個筆記子集合涣脚,由于前面用了genre屬性做分組,分組保存的形式寥茫,類似key遣蚀、value的方式,key保存的是分組的genre屬性的值纱耻,value保存的是某個分組下的筆記的集合芭梯。所以,group.key的值就是genre分類弄喘,把它當成一個三級標題輸出玖喘。
? ? ? 第二個是dv.table()的用法,這里不展開講蘑志,用到了排序和map構(gòu)造二維數(shù)組作為填充表格的內(nèi)容累奈,這個也放到第三步里我們看源代碼來詳細解讀贬派。
? ? ? 第二步,知其然的部分就說到這费尽,篇幅有限赠群,下篇繼續(xù)。