Nuxt3- v-for content | content 裡面的陣列

Nagiichinichi
11 min readSep 12, 2022

--

在研究nuxt3 技術時,討論的文章還不是很多,遇到了不少坑,在這裡簡單分享自己的研究成果,也順便幫未來的自己做個紀錄。

這篇文章為使用nuxt3 content,資料結構為三層的心得分享。

文章摘要

Content 為nuxt3裡面一個很好用的功能,只要在content資料夾中準備markdown檔案(其他文件檔案好像也可以,參考https://content.nuxtjs.org/ 文件說明),就可以render裡面的資料。

做靜態網站時,把文字、圖片等資料集中管理,做更改的時候就可以很快速!甚至更改的人也可以不用看懂網站的語法結構,只要看得懂json檔案格式,對照文字,就可以快速地更改網站內容。

首先會介紹content的基本配置,官方文件寫的<ContentList> & <ContentDoc> 的render基本的使用方法↓

例如網站中想要有一頁面為blog,裡面列出所有的blog標題,點選標題可以進入文章詳細頁面時,就可以簡單地使用,也就是以下這位大神在demo nuxt3範本時,Post 頁面的使用方法↓

再來是介紹再進階一層,ContenDoc還有一個陣列v-for來取得陣列資料。資料結構為一個根(例如:文章),下面有類別(文章分類),類別下有細項(文章本身)的三層結構,主要是參考以下文章↓

Power your blog with Nuxt Content (openreplay.com)

content 基本配置

  1. installaiton

首先先按照官方文件的說明— Installation,先install npm content到專案。以下指令任選一個使用就可以了

yarn add --dev @nuxt/content// or 
npm install --save-dev @nuxt/content
// or
pnpm add -D @nuxt/content

然後很重要的,到nuxt.config.ts增加modules '@nuxt/content'

@ nuxt.config.ts


export default defineNuxtConfig({
modules: [
'@nuxt/content'
],
content: {
// https://content.nuxtjs.org/api/configuration
}
})

2. 新增content 資料夾

先新增一個名為content的資料夾,裡面放contentDoc想要render的markdown檔案,nuxt3會自動match pages content 兩個資料夾裡面相同名稱的資料夾,例如:我想要一個名為blog的頁面,裡面有文章,資料夾配置如下↓

/ mySite
- nuxt.config.ts
- app.vue
- /pages
-- index.vue
-- /blog
--- index.vue
--- [slut].vue
- /content
-- /blog
--- post01.md
--- post02.md
--- post03.md
  • pages/blog/index.vue 為 blog 頁面的首頁,網址為 mySite/blog
  • pages/blog/[slut].vue 則是到時候render的內頁,網址為 mySite/blog/post01.md(會抓取你content/blog的md檔案名稱)

3. 準備資料.md

關於markdown的資料寫法,請參考官方說明Content的文件↓

在這邊分享我的md檔,內容為上網抓世界知名博物館的名稱、圖片(維基百科)、與說明文字↓

有三點小提醒:

  1. 上面是資料名稱,需要 欄位:'欄位值',以及下面是content的內容,不加引號以外,欄位都可以依照自己的需要做編排以及取名
  2. 官方的文件說明中,md檔還可以加入標籤以及樣式,不過我沒有用到
  3. 每一個md檔的內容欄位,也就是下面"The British Museum….."的地方不能是空的,不然content的內頁會噴錯(可以不要渲染這裡但不能不填)

也可以直接到我的github上看範例↓(git commit: ‘ contetn version 1’)

小補充:可以上網搜尋json editor,例如:https://jsoneditoronline.org/http://www.objgen.com/json…等等幫你快速編輯json格式的資料

4. ContetnList

前置作業都做好以後,終於來到最重要的部分啦,先來分享看程式碼與頁面呈現,再來詳細說明

@ pages/blog/index.vue

<template>
<div>
<h1>blog post--museum</h1>
<ContentList v-slot="{ list }">
<div v-for="article in list" :key="article._path">
<h2>{{ article.name }} </h2>
<h3>{{ article.date }}</h3>
<img :src="article.img">
<h3>{{ article.description }}</h3>
<div> <a :href="article._path">閱讀更多→</a></div>
<hr/>
</div>
</ContentList>
</div>
</template>

@ pages/blog/[slut].vue

<template>
<div>
<ContentDoc v-slot="{ doc }">
<h1>{{ doc.name }}</h1>
<img :src="doc.img">
<small>{{ doc.date }}</small>
<h2>{{ doc.description }}</h2>
<ContentRenderer :value="doc"/>
</ContentDoc>
</div>
</template>
頁面呈現結果 — blog/index.vue
頁面呈現結果 — blog/post02

在pages/blog/index.vue 中的”list”是固定的名稱,讓nuxt3 找到在content資料夾中,與pages資料夾相同名稱的資料夾中的檔案名稱,進行資料的渲染。path路徑名稱就會自動對應到content資料夾中的md檔案名稱。

“article”則是取得v-for陣列中的值時,可以自己取的代表該陣列的名稱,要注意的是,v-for=”a in b” ,a不能跟b叫相同的名字,通常的命名習慣都會是,後面是前面的複數型,例如:v-for=”book in books”。

<ContentList v-slot=”{ list }”></ContentList>

代表這區域是要render content的範圍,如果不小心把要v-for 的陣列寫在<ContentList>的區域外面,就會噴錯,這很重要!

小補充: 身為初學者,我常常會不小心搞混在綁定值時,是{{ article.name }} 還是是:article.img,甚麼時候是{{ }} 、甚麼時候是v-bind;這邊提供一個記憶點~寫在”內容”時候(例如:h2的內容)是雙括號<h2>{{ article.name }}</h2>;綁在”標籤裡面”是用v-bind ,不用加雙括號,例如<img :src=”aritcle.img”>,這樣以後就不會再寫錯啦。

在pages/blog/[slut].vue,也就是內頁的部分,<ContentDoc>用法跟<ContentDoc>差不多,只是多了個 <ContentRenderer :value=”doc”/>可以用,也就是render md檔中下面的內容欄位(記得在每個md檔案中,不能有一個檔案這裡是空的,不然會噴錯給你看)

content 第三層資料

說第三層資料有點複雜,其實就是:「contetn資料夾裡面的md檔裡可不可以塞陣列資料?」答案是「可以!」

在上面的範例md檔中,都加進一筆陣列資料↓

tags : [
{ 'id':'1', 'name':'Travel'},
{ 'id':'2', 'name':'England'}
]
tags: [{….},]

然後在[slut].vue內頁地方加入一行v-for=”tag in doc.tags”陣列資料出來↓

[slut].vue
內頁呈現結果

完整可參考我的github↓

https://github.com/nagiqq/nuxt3_content

參考資料

  1. nuxt3 content

https://v3.nuxtjs.org/guide/directory-structure/content#content-directory

2. content.org

3. nuxt3-awesome-starter

4. content v-for

Power your blog with Nuxt Content (openreplay.com)

--

--