ASTRO中的内容集合

188 阅读3分钟

什么是内容集合?

astro中内容集合指的就是

src/content/ 目录中的顶级文件夹。只允许在 src/content 目录中。

内容集合的内容条目存储在 Markdown (.md) 或 MDX (.mdx) 文件中。

官方建议命名方案:

(小写,破折号而不是空格) ,以便更容易地查找和组织内容。

src/content/
	文件夹newsletter/  “newsletter” 集合
    week-1.md 一个集合条目
    week-2.md 一个集合条目
    week-3.md 一个集合条目

如何使用内容集合?

  1. 定义多集合:

    src/content/
    	newsletter/  “newsletter” 集合1
        week-1.md 一个集合条目
        week-2.md 一个集合条目
        week-3.md 一个集合条目
    	blog/  “newsletter” 集合2
        week-1.md 一个集合条目
        week-2.md 一个集合条目
        week-3.md 一个集合条目
    
  2. 添加子目录更好的归类集合内容

    src/content/
    	docs/
    		en/
    			…
    		es/
    			…
    		de/
    			…
    
  3. 使用schema定义集合条目的格式并导出:

    src/content/config.ts 文件(也支持 .js 和 .mjs)。用它来配置你的内容集合。

    Markdown (type: 'content') 的内容创作格式或是像 JSON 及 YAML (type: 'data') 的数据格式

    //src/content/config.ts
    // 1. 从 `astro:content` 导入
    import { defineCollection } from 'astro:content';
    // 2. 定义集合
    const blogCollection = defineCollection({ /* ... */ });
    // 3. 导出一个 `collections` 对象来注册集合
    //    这个键应该与 `src/content` 中的集合目录名匹配
    export const collections = {
      'blog': blogCollection,
    }
    
    //导出多个
    const blogCollection = defineCollection({
      type: 'content',
      schema: z.object({ /* ... */ })
    });
    const newsletter = defineCollection({
      type: 'content',
      schema: z.object({ /* ... */ })
    });
    const authors = defineCollection({
      type: 'data',
      schema: z.object({ /* ... */ })
    });
    
    export const collections = {
      'blog': blogCollection,
      'newsletter': newsletter,
      'authors': authors,
    };
    
    //也可以把schema 抽离
    // 1. 导入你的实用工具和 schema
    import { defineCollection } from 'astro:content';
    import { blogSchema, authorSchema } from '../schemas';
    
    // 2. 定义你的集合
    const blogCollection = defineCollection({
      type: 'content',
      schema: blogSchema,
    });
    const authorCollection = defineCollection({
      type: 'data',
      schema: authorSchema,
    });
    
    // 3. 导出多个集合以注册它们
    export const collections = {
      'blog': blogCollection,
      'authors': authorCollection,
    };
    
    //还可以导入三方的schema
    import { blogSchema } from 'my-blog-theme';
    const blogCollection = defineCollection({ type: 'content', schema: blogSchema });
    
    // 导出从 'my-blog-theme' 导入的 schema 为 `blog` 集合
    export const collections = {
      'blog': blogCollection,
    };
    
    自定义 slugs
    astro 中,可以定义 slug 三个也许不够吗酷生成一个友好的url地址。
    
    ---
    title: 我的博客文章
    slug: my-custom-slug/supports/slashes
    ---
    你的博客文章内容在这里。
    
  4. 集合引用

    reference() 函数,就是将数据通过id进行关联,避免一份数据多个副本,导致后期补好维护.

    定义引用:
    
    import { defineCollection, reference, z } from 'astro:content';
    
    const blog = defineCollection({
      type: 'content',
      schema: z.object({
        title: z.string(),
    															----		    // 通过 `id` 引用 `authors` 集合中的单个作者
        author: reference('authors'),
    															----	    // 通过 `slug` 引用 `blog` 集合中的相关帖子数组
        relatedPosts: z.array(reference('blog')),
      })
    });
    
    const authors = defineCollection({
      type: 'data',
      schema: z.object({
        name: z.string(),
        portfolio: z.string().url(),
      })
    });
    
    export const collections = { blog, authors };
    
    使用引用:
    	***---
    	title: "Welcome to my blog"
    	author: ben-holmes # 引用 `src/content/authors/ben-holmes.json`
    	relatedPosts:
    	- about-me # 引用 `src/content/blog/about-me.md`
    	- my-year-in-review # 引用 `src/content/blog/my-year-in-review.md`
    	---***
    
  5. 查询集合

    getCollection() 和 getEntry()

    1. getCollection() 可筛选,传递 “filter” ,可以基于 idslug 或 data (frontmatter) 过滤。 type: content 的集合,还可通过 slug 过滤。

    2. filter 支持嵌套目录筛选。 id 包含完整嵌套路径,可以 id 进行筛选,返回项目:

      import { getCollection, getEntry } from 'astro:content';
      
      // 获取集合中的所有条目。
      // 需要集合的名称作为参数。
      // 示例:检索 `src/content/blog/**`
      const allBlogPosts = await getCollection('blog');
      
      // 从集合中获取单个条目。
      // 需要集合的名称以及
      // 条目 `slug`(内容集合)或 `id`(数据集合)
      // 示例:检索 `src/content/authors/grace-hopper.json`
      const graceHopperProfile = await getEntry('authors', 'grace-hopper');
      
      // 例子:使用 `draft: true` 过滤内容条目
      import { getCollection } from 'astro:content';
      const draftBlogEntries = await getCollection('blog', ({ data }) => {
        return data.draft !== true;
      });
      
      // 示例:仅当构建生产时,才过滤掉具有 `draft: true` 的内容条目
      import { getCollection } from 'astro:content';
      const blogEntries = await getCollection('blog', ({ data }) => {
        return import.meta.env.PROD ? data.draft !== true : true;
      });
      
      // 例子:按集合中的子目录筛选条目
      import { getCollection } from 'astro:content';
      const englishDocsEntries = await getCollection('docs', ({ id }) => {
        return id.startsWith('en/');
      });
      
      ## 数据集合之间的关联,查询:
      ---
      import { getEntry, getEntries } from 'astro:content';
      
      const blogPost = await getEntry('blog', 'welcome');
      
      // 检索单一引用
      const author = await getEntry(blogPost.data.author);
      // 检索集合中的引用数据
      const relatedPosts = await getEntries(blogPost.data.relatedPosts);
      ---
      
      <h1>{blogPost.data.title}</h1>
      <p>作者:{author.data.name}</p>
      
      <!-- ... -->
      
      <h2>你可能也喜欢:</h2>
      {relatedPosts.map(p => (
        <a href={p.slug}>{p.data.title}</a>
      ))}
      

      这两个函数都返回由 CollectionEntry 类型定义的内容条目。

  6. 使用查询出来的数据:

    1. 通过 {} 包裹后,可使用js语法

      ---
      import { getCollection } from 'astro:content';
      const blogEntries = await getCollection('blog');
      ---
      <ul>
        {blogEntries.map(blogPostEntry => (
          <li>
            <a href={`/my-blog-url/${blogPostEntry.slug}`}>{blogPostEntry.data.title}</a>
            <time datetime={blogPostEntry.data.publishedDate.toISOString()}>
              {blogPostEntry.data.publishedDate.toDateString()}
            </time>
          </li>
        ))}
      </ul>