接下來我們終於要來製作一直放著的標籤相關功能的內容,當我們的blog內容變多的時候,我們可以添加一個標籤的功能,讓使用者點擊標籤的時候,就可以得到擁有該標籤所有文章,在這過程中我們會用到動態路由的方式去呈現
我們移除了舊的tag頁面,並且在pages裡面新增了一個tags的資料夾,裡面建立了一個名為[tag].astro的檔案,這個檔案中的[tag],將會變成我們未來點擊標籤時所提供的參數,在[tag].astro的檔案中我們寫了之前寫好的布局,並且從astro.prams中提取出來名為tags的變數,而posts將會是我們文章的來源
值得一提的是psot的文章用props的方式去取得資料,但我們的文章應該是要根據我們所選擇的tag去做篩選,而不是用父元件傳參數的方式去執行,那麼我們該怎麼做呢?
可以看到圖片中寫了一個非同步的async function,接下來我們要來逐步講解裡面的內容:
const allPosts = await Astro.glob('../posts/*.md');
Astro.glob
方法異步地讀取 ../posts/
目錄下的所有 .md
文件。這些 Markdown 文件會被解析為包含 frontmatter
和 content
的物件。allPosts
是一個包含所有文章(Markdown 文件)物件的陣列。const tags = allPosts.map((post) => post.frontmatter.tags);
map()
方法遍歷 allPosts
陣列,並從每篇 post
物件的 frontmatter
中提取出 tags
。frontmatter
是每篇 Markdown 文件原本的資料(如標題、標籤等)。結果會是一個二維陣列(陣列中還有陣列),每篇文章都包含自己的標籤陣列。const flatTags = tags.flat();
flat()
方法將二維陣列轉換為一維陣列。因為 tags
是一個二維陣列(每篇文章有多個標籤),所以這一步會將它展平成一個一維的標籤陣列。uniqueTags = [...new Set(flatTags)];
Set
來移除重複的標籤。Set
是一種只允許唯一值的資料結構,將 flatTags
放進 Set
之後,自動移除了重複的標籤。然後使用 [...new Set(flatTags)]
將其轉換回普通陣列 uniqueTags
,這個陣列只包含不重複的標籤。return uniqueTags.map((tag) =>
const filteredPosts = allPosts.filter((post) => post.frontmatter.tags.includes(tag));
filter()
方法從 allPosts
中篩選出包含當前標籤 tag
的文章。post.frontmatter.tags.includes(tag)
檢查該篇文章的標籤數組中是否包含當前的標籤 tag
。filteredPosts
是一個包含所有符合該標籤的文章的陣列。return { params: { tag }, props: { posts: filteredPosts } };
map()
返回一個物件,包含兩個屬性:
params
:指定動態路徑的參數(即當前的標籤 tag
)。在 Astro 中,動態路由可以生成 /tags/[tag]
形式的 URL。props
:傳遞給該頁面的屬性。這裡傳遞的是 posts
,即包含當前標籤 tag
的文章。.md
文件。props
傳遞給靜態頁面。接下來讓我們測試一下結果
可以看到我們在網址上面改成了”tags/我們想要的標籤”,那麼我們的頁面就會幫我們過濾含有該標籤的文章,這樣我們就實現了過濾文章的功能了!