前段时间,我在思考我的上网习惯,更具体地说,是我在阅读时真正喜欢什么。这就是我通常做的事情:我运行一个查询,然后我只是让自己被最有趣的链接引导。我总是发现自己在阅读有关某人经历的博客文章,这些文章与我最初输入的查询完全无关。

博客是分享经验、信仰或推荐的绝佳方式。Strapi可帮助您创建博客!所以,我很确定你现在明白这篇文章的内容了。让我们学习如何使用您最喜欢的技术Strapi创建博客。

目标

如果您熟悉我们的博客,那么您一定已经看到我们发布了一系列教程,介绍如何使用 Strapi 和大量前端框架制作博客:

  • 反应

  • Next.js

  • 图片。 js

  • 盖茨比

本文的目标是能够使用 Strapi 作为后端、Nuxt 作为前端以及 Apollo 使用 GraphQL 请求 Strapi API 创建一个博客网站。

点击这里访问 GitHub 上的源代码。

先决条件

要学习本教程,您需要在计算机上安装最新版本的 Strapi 和 Nuxt,但别担心,我们将一起安装它们!

您还需要安装 Node.js v14,仅此而已。

第 1 步:后端设置

从 beta.9 开始,我们有一个很棒的包create strapi-app,它允许您在几秒钟内创建一个 Strapi 项目,而无需全局安装 Strapi,所以让我们尝试一下。

  • 创建一个 blog-strapi 文件夹并进入!
    mkdir blog-strapi
    cd blog-strapi

进入全屏模式 退出全屏模式

  • 使用博客模板创建您的 Strapi 后端文件夹;在终端中复制并粘贴以下命令行:
    yarn create strapi-app backend --quickstart --no-run

进入全屏模式 退出全屏模式

这个单一的命令行将为您的后端创建所需的一切。确保添加--no-run标志,因为它会阻止您的应用程序自动启动服务器,因为

SPOILER ALERT:我们需要先安装一些很棒的 Strapi 插件。

现在您知道我们需要安装一些插件来增强您的应用程序,让我们安装我们最受欢迎的插件之一——GraphQL 插件:

    cd backend
    yarn strapi install graphql
    yarn develop

进入全屏模式 退出全屏模式

在http://localhost:1337 打开你的 Strapi 开发服务器。

[Strapi - 管理员](https://res.cloudinary.com/practicaldev/image/fetch/s--3wIT2hNV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments .dropbox.com/s_4AF4FDEDF16A3DF3B0654D64C2F33EDD6CA7EA05F0D813E76F8984F96837F085_1639072772822_image.png)

安装完成后,您终于可以启动您的 Strapi 开发服务器并创建您的第一个管理员用户。那是在您的应用程序中拥有所有权限的人,因此请确保输入正确的密码; (password123) 真的不安全。

[! Strapi - 主页] (https://res.cloudinary.com/practicaldev/image/fetch/s--uy6vhewf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments .dropbox.com / s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653127217640_Capture% 2Bdcran% 2Bde% 2B2022-05-21% 2B11-00-05.png)

好的!现在 Strapi 已准备就绪,您将创建 Nuxt 应用程序。

第 2 步:前端设置

好了,最简单的部分已经完成了,让我们动手开发我们的博客吧!

  • 通过在./blog-strapi中运行以下命令来创建 Nuxt 项目:
    yarn create nuxt-app frontend

进入全屏模式 退出全屏模式

注意:终端会提示您输入项目的一些详细信息。由于它们与我们的博客并不真正相关,您可以忽略它们。不过,我强烈建议您阅读文档。所以继续吧,尽情享受吧,然后一直按 Enter 键!

同样,安装完成后,您可以启动前端应用程序以确保一切正常。

    cd frontend  
    yarn dev

进入全屏模式 退出全屏模式

  • 在http://localhost:3000/打开你的 Nuxt.js 开发服务器

由于您可能希望人们阅读您的博客或使其“可爱和漂亮”,我们将使用流行的 CSS 框架进行样式设置:UIkit和Apollo GraphQL使用GraphQL查询 Strapi。

第 3 步:使用 GraphQL 查询 Strapi

在运行以下命令之前,请确保您位于frontend文件夹中。

  • 通过运行以下命令为 Apollo 安装所有必要的依赖项:
    // Ctrl + C to close Nuxt.js process
    yarn add @nuxtjs/apollo

进入全屏模式 退出全屏模式

Apollo Client 是一个功能齐全的缓存 GraphQL 客户端,集成了 Vue、React 等。它允许您轻松构建通过 GraphQL 获取数据的 UI 组件。

  • @nuxtjs/apollo添加到模块部分,Apollo 配置在./frontend/nuxt.config.js
    // nuxt.config.js

    export default {
      modules: [
        '@nuxtjs/apollo',
      ],

      apollo: {
        clientConfigs: {
          default: {
            httpEndpoint: process.env.BACKEND_URL || "http://localhost:1337/graphql",
          }
        }
      },
    }

进入全屏模式 退出全屏模式

我们还需要为我们的 Strapi 基本 url 使用一个环境变量,在nuxt.config.js文件的末尾添加一个新的env部分:

    // nuxt.config.js

    export default {
      env: {
        strapiBaseUri: process.env.API_URL || "http://localhost:1337"
      },
    }

进入全屏模式 退出全屏模式

伟大的! 阿波罗现已准备就绪。 🚀

第 4 步:使用 UIkit 进行样式设置

UIkit 是一个轻量级的模块化前端框架,用于开发快速而强大的 Web 界面。

  • 通过运行以下命令安装 UIkit:
    yarn add uikit

进入全屏模式 退出全屏模式

现在您需要在 Nuxt 应用程序中初始化 UIkit 的 JS。您将通过创建一个新插件来做到这一点。

  • 创建一个./frontend/plugins/uikit.js文件并复制/粘贴以下代码:
    import Vue from 'vue'

    import UIkit from 'uikit/dist/js/uikit-core'
    import Icons from 'uikit/dist/js/uikit-icons'

    UIkit.use(Icons)
    UIkit.container = '#__nuxt'

    Vue.prototype.$uikit = UIkit

Add the following sections to your `nuxt.config.js` file:

    // nuxt.config.js

    export default {
     css: [
        'uikit/dist/css/uikit.min.css',
        '@assets/css/main.css'
      ],

      plugins: [
        { src: '~/plugins/uikit.js', ssr: false }
      ]
    }

As you can see, you are including both UIkit and `main.css` files! We just need to create the `./frontend/assets/css/main.css` file.

    a {
      text-decoration: none;
    }

    h1  {
      font-family: Staatliches;
      font-size: 120px;
    }

    #category {
       font-family: Staatliches;
       font-weight: 500;
    }

    #title {
      letter-spacing: .4px;
      font-size: 22px;
      font-size: 1.375rem;
      line-height: 1.13636;
    }

    #banner {
      margin: 20px;
      height: 800px;
    }

    #editor {
      font-size: 16px;
      font-size: 1rem;
      line-height: 1.75;
    }

    .uk-navbar-container {
      background: #fff !important;
      font-family: Staatliches;
    }

    img:hover {
      opacity: 1;
      transition: opacity 0.25s cubic-bezier(0.39, 0.575, 0.565, 1);
    }

**Note:** You don't need to understand what's in this file. It's just some styling ;)

Let's add a beautiful font [Staatliches](https://fonts.google.com/specimen/Staatliches) to the project! Add the following code to your `link` section in your `nuxt.config.js`

    // nuxt.config.js

    export default {
      link: [
        { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Staatliches' }
      ],
    }

进入全屏模式 退出全屏模式

完美! 运行yarn dev以重新启动您的服务器,并准备好对您的应用程序的首页留下深刻印象!

[Nuxt.js 应用程序 - http://localhost:3000/](https://res.cloudinary.com/practicaldev/image/fetch/s--bHIqmgrG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto %2Cw_880/https://paper-attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653128890833_Capture%2Bdcran%2Bde%2B2022-045-21%2B2022-045-21%2

太棒了! 是时候稍微构建一下我们的代码了。

第五步:设计数据结构

最后,我们现在将通过创建文章内容类型来创建文章的数据结构。

  • 进入您的 Strapi 管理面板并点击“Content-Type Builder”

[内容类型生成器](https://res.cloudinary.com/practicaldev/image/fetch/s--egh_QR-d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// paper-attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653129086084_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-31-17.png)

  • 点击“创建新的收藏类型”

[Content-Type Builder - 文章](https://res.cloudinary.com/practicaldev/image/fetch/s--n7eXJG3n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// paper-attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653129168293_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-32-38.png)

现在您将被要求为您的内容类型创建所有字段

[![Content-Type Builder - 第]条(https://res.cloudinary.com/practicaldev/image/fetch/s--qpKCamNi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653129217167_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-33-22.png)](https://res.cloudinary.com/practicaldev/image/fetch/s--qpKCamNi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// paper-attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653129217167_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-33-22.png)

  • 创建以下内容:

  • 字段文本“标题”

  • FieldRich Text “内容”

  • Field Media“图像”,单张图像

按保存! 到此,您的“文章”内容类型已创建。

[Content-Type Builder - 文章](https://res.cloudinary.com/practicaldev/image/fetch/s--29Iui9Cm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// paper-attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653129508786_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-38-17.png)

您可能想要创建您的第一篇文章,但在此之前我们还有一件事要做:授予对文章内容类型的访问权限

  • 单击设置,然后单击角色,然后单击“公共”角色

[设置 - 角色](https://res.cloudinary.com/practicaldev/image/fetch/s--3Q9KmQHI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments .dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653129655564_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-40-40.png)

惊人的!您现在应该准备好创建您的第一篇文章并在 GraphQL Playground 上获取它。

现在,创建您的第一篇文章!这是一个例子:

[互联网自己的男孩](https://res.cloudinary.com/practicaldev/image/fetch/s--YP1RHdn---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper -attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653129970935_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-45-58.png)

伟大的!现在您可能想要通过 API 实际获取文章的那一刻!转到http://localhost:1337/api/articles是不是很酷!

您还可以使用GraphQL Playground。

[示例](https://res.cloudinary.com/practicaldev/image/fetch/s---clPLxKs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments。 dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_16531399855_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-48-09.png)

您可能想要为您的文章(新闻、趋势、观点)分配一个类别。您将通过在 Strapi 中创建另一个内容类型来完成此操作。

使用以下字段创建“类别”内容类型

  • 字段文本“名称”内容类型生成器 - 类别

按保存!

Article 内容类型中创建一个新字段,它是一个 RelationCategory has many Articles,如下所示:

[Content-Type Builder - 文章](https://res.cloudinary.com/practicaldev/image/fetch/s--7vIwD9R2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// paper-attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_165313344151_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-52-14.png)

再次打开 Settings 然后 Roles 并单击“Public”角色,然后检查类别findfindone路线并保存。

[设置-角色](https://res.cloudinary.com/practicaldev/image/fetch/s--Jv4ruaYH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments .dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_165313481053_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-54-31.png)

现在您可以在右侧框中为您的文章选择一个类别。

[内容管理器 - 互联网自己的男孩](https://res.cloudinary.com/practicaldev/image/fetch/s--HHtrdn7H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// /paper-attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_165313557208_Capture%2Bdcran%2Bde%2B2022-05-21%2B11-55-45.png)

现在我们已经熟悉了 Strapi,让我们在前端部分工作吧!

第 6 步:创建应用程序的布局

您可以通过创建自己的layouts/default.vue文件来更改 Nuxt.js 应用程序的默认布局。

    <template>
      <div>
        <nav class="uk-navbar-container" uk-navbar>
          <div class="uk-navbar-left">
            <ul class="uk-navbar-nav">
              <li>
                <a href="#modal-full" uk-toggle
                  ><span uk-icon="icon: table"></span
                ></a>
              </li>
              <li>
                <a href="/">Strapi Blog </a>
              </li>
            </ul>
          </div>
          <div class="uk-navbar-right">
            <ul class="uk-navbar-nav">
              <li v-for="category in categories.data" :key="category.id">
                <NuxtLink
                  :to="{ name: 'categories-id', params: { id: category.id } }"
                  >{{ category.attributes.name }}
                </NuxtLink>
              </li>
            </ul>
          </div>
        </nav>
        <div id="modal-full" class="uk-modal-full" uk-modal>
          <div class="uk-modal-dialog">
            <button
              class="uk-modal-close-full uk-close-large"
              type="button"
              uk-close
            ></button>
            <div
              class="uk-grid-collapse uk-child-width-1-2@s uk-flex-middle"
              uk-grid
            >
              <div
                class="uk-background-cover"
                style="
                  background-image: url('https://images.unsplash.com/photo-1493612276216-ee3925520721?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3308&q=80 3308w');
                "
                uk-height-viewport
              ></div>
              <div class="uk-padding-large">
                <h1 style="font-family: Staatliches">Strapi blog</h1>
                <div class="uk-width-1-2@s">
                  <ul class="uk-nav-primary uk-nav-parent-icon" uk-nav>
                    <li v-for="category in categories.data" :key="category.id">
                      <NuxtLink
                        class="uk-modal-close"
                        :to="{ name: 'categories-id', params: { id: category.id } }"
                        >{{ category.attributes.name }}
                      </NuxtLink>
                    </li>
                  </ul>
                </div>
                <p class="uk-text-light">Built with strapi</p>
              </div>
            </div>
          </div>
        </div>
        <Nuxt />
      </div>
    </template>

    <script>
    export default {
      data() {
        return {
          categories: {
            data: [],
          },
        };
      },
    };
    </script>

进入全屏模式 退出全屏模式

如您所见,categories列表为空。事实上,您希望能够在导航栏中列出每个类别。为此,我们需要使用 Apollo 获取它们,让我们编写查询!

  • 在里面创建一个apollo/queries/category文件夹和一个categories.gql文件,代码如下:
    query {
      categories {
        data {
          id
          attributes {
            name
          }
        }
      }
    }

进入全屏模式 退出全屏模式

  • default.vue文件中的script标记替换为以下代码:
    <script>
    import categoriesQuery from "~/apollo/queries/category/categories";

    export default {
      data() {
        return {
          categories: {
            data: [],
          },
        };
      },
      apollo: {
        categories: {
          prefetch: true,
          query: categoriesQuery,
        },
      },
    };
    </script>

进入全屏模式 退出全屏模式

注意: 当前代码不适合显示很多类别,因为您可能会遇到 UI 问题。

由于这篇博文应该很短,我会让你改进代码,可能会添加一个延迟加载或其他东西。 目前,这些链接不起作用,您将在本教程后面进行处理 :)

步骤 7:创建文章组件

该组件将在不同页面上显示您的所有文章,因此通过组件列出它们并不是一个坏主意。

  • 创建一个包含以下内容的components/Articles.vue文件:
    <template>
      <div>
        <div class="uk-child-width-1-2" uk-grid>
          <div>
            <router-link
              v-for="article in leftArticles"
              :to="{ name: 'articles-id', params: { id: article.id } }"
              class="uk-link-reset"
              :key="article.id"
            >
              <div class="uk-card uk-card-muted">
                <div v-if="article.attributes.image.data" class="uk-card-media-top">
                  <img
                    :src="api_url + article.attributes.image.data.attributes.url"
                    alt=""
                    height="100"
                  />
                </div>
                <div class="uk-card-body">
                  <p
                    id="category"
                    v-if="article.attributes.category.data"
                    class="uk-text-uppercase"
                  >
                    {{ article.attributes.category.data.attributes.name }}
                  </p>
                  <p id="title" class="uk-text-large">
                    {{ article.attributes.title }}
                  </p>
                </div>
              </div>
            </router-link>
          </div>
          <div>
            <div class="uk-child-width-1-2@m uk-grid-match" uk-grid>
              <router-link
                v-for="article in rightArticles"
                :to="{ name: 'articles-id', params: { id: article.id } }"
                class="uk-link-reset"
                :key="article.id"
              >
                <div class="uk-card uk-card-muted">
                  <div
                    v-if="article.attributes.image.data"
                    class="uk-card-media-top"
                  >
                    <img
                      :src="api_url + article.attributes.image.data.attributes.url"
                      alt=""
                      height="100"
                    />
                  </div>
                  <div class="uk-card-body">
                    <p
                      id="category"
                      v-if="article.attributes.category.data"
                      class="uk-text-uppercase"
                    >
                      {{ article.attributes.category.data.attributes.name }}
                    </p>
                    <p id="title" class="uk-text-large">
                      {{ article.attributes.title }}
                    </p>
                  </div>
                </div>
              </router-link>
            </div>
          </div>
        </div>
      </div>
    </template>

    <script>
    export default {
      data() {
        return {
          api_url: process.env.strapiBaseUri,
        };
      },
      props: {
        articles: Object,
      },
      computed: {
        leftArticlesCount() {
          return Math.ceil(this.articles.data.length / 5);
        },
        leftArticles() {
          return this.articles.data.slice(0, this.leftArticlesCount);
        },
        rightArticles() {
          return this.articles.data.slice(
            this.leftArticlesCount,
            this.articles.length
          );
        },
      },
    };
    </script>

进入全屏模式 退出全屏模式

如您所见,由于 GraphQl 查询,您正在获取文章,让我们来写吧!

  • 创建一个新的apollo/queries/article/articles.gql文件,其中包含以下内容:
    query {
      articles {
        data {
          id
          attributes {
            title
            content
            image {
              data {
                attributes {
                  url
                }
              }
            }
            category {
              data {
                attributes {
                  name
                }
              }
            }
          }
        }
      }
    }

进入全屏模式 退出全屏模式

**太棒了!**现在,您可以创建您的主页。

步骤 8:索引页

您想在索引页面上列出每篇文章,让我们使用我们的新组件!将pages/index.vue文件中的代码更新为:

    <template>
      <div>
        <div class="uk-section">
          <div class="uk-container uk-container-large">
            <h1>Strapi blog</h1>
            <Articles :articles="articles"></Articles>
          </div>
        </div>
      </div>
    </template>

    <script>
    import articlesQuery from "~/apollo/queries/article/articles";
    import Articles from "~/components/Articles";
    export default {
      data() {
        return {
          articles: {
            data: [],
          },
        };
      },
      components: {
        Articles,
      },
      apollo: {
        articles: {
          prefetch: true,
          query: articlesQuery,
        },
      },
    };
    </script>

进入全屏模式 退出全屏模式

伟大的!您现在已经可以通过 GraphQL API 实际获取您的文章了!

[Nuxt.js - 主页](https://res.cloudinary.com/practicaldev/image/fetch/s--V5U1WVik--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper -attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653132256667_Capture%2Bdcran%2Bde%2B2022-05-21%2B12-23-52.png)

你可以看到,如果你点击文章,什么都没有。让我们一起创建文章页面!

步骤 9:创建文章页面

  • 创建一个pages/articles文件夹和一个新的_id.vue文件,其中包含以下内容:
    <template>
      <div>
        <div
          v-if="article.data.attributes.image.data"
          id="banner"
          class="uk-height-small uk-flex uk-flex-center uk-flex-middle uk-background-cover uk-light uk-padding"
          :data-src="api_url + article.data.attributes.image.data.attributes.url"
          uk-img
        >
          <h1>{{ article.data.attributes.title }}</h1>
        </div>
        <div class="uk-section">
          <div class="uk-container uk-container-small">
            <div v-if="article.data.attributes.content" id="editor">
              {{ article.data.attributes.content }}
            </div>
            <p v-if="article.data.publishedAt">
              {{ article.data.attributes.publishedAt }}
            </p>
          </div>
        </div>
      </div>
    </template>

    <script>
    import articleQuery from "~/apollo/queries/article/article";

    export default {
      data() {
        return {
          article: {
            data: [],
          },
          api_url: process.env.strapiBaseUri,
        };
      },
      apollo: {
        article: {
          prefetch: true,
          query: articleQuery,
          variables() {
            return { id: parseInt(this.$route.params.id) };
          },
        },
      },
    };
    </script>

进入全屏模式 退出全屏模式

在这里您只获取一篇文章,让我们在其后面编写查询!创建一个apollo/queries/article/article.gql包含以下内容:

    query Articles($id: ID!) {
      article(id: $id) {
        data {
          id
          attributes {
            title
            content
            image {
              data {
                attributes {
                  url
                }
              }
            }
            publishedAt
          }
        }
      }
    }

进入全屏模式 退出全屏模式

好的,您可能希望将您的内容显示为 Markdown

  • 安装markdownityarn add @nuxtjs/markdownit

  • 安装date-fnsyarn add @nuxtjs/date-fns

  • 将其添加到nuxt.config.js文件中的模块中,并在// nuxt.config.js下方添加 markdownit 对象配置。

    export default {
      // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
      buildModules: [
        '@nuxtjs/date-fns',
      ],

      // Modules: https://go.nuxtjs.dev/config-modules
      modules: [
        '@nuxtjs/apollo',
        '@nuxtjs/markdownit'
      ],

      // [optional] markdownit options
      // See https://github.com/markdown-it/markdown-it
      markdownit: {
        preset: 'default',
        linkify: true,
        breaks: true,
        injected: true
      }
    }

进入全屏模式 退出全屏模式

  • 通过替换负责显示内容的行,使用它来显示_id.vue文件中的内容。// pages/articles/_id.vue

[Nuxt.js - 文章页面](https://res.cloudinary.com/practicaldev/image/fetch/s--7ypeoamG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// paper-attachments.dropbox.com/s_12483C53855A83F56330D4447B577BD987D1968F6A4F6C51CC4B36A4E5BF0905_1653311681047_Capture%2Bdcran%2Bde%2B2022-05-23%2B14-14-26.png)

第 10 步:类别

现在让我们为每个类别创建一个页面!在其中创建一个pages/categories文件夹和一个_id.vue文件,其中包含以下内容:

    <template>
      <div>
        <client-only>
          <div class="uk-section">
            <div class="uk-container uk-container-large">
              <h1>{{ category.data.attributes.name }}</h1>
              <Articles :articles="category.data.attributes.articles"></Articles>
            </div>
          </div>
        </client-only>
      </div>
    </template>

    <script>
    import articlesQuery from "~/apollo/queries/article/articles-categories";
    import Articles from "~/components/Articles";
    export default {
      data() {
        return {
          category: {
            data: [],
          },
        };
      },
      components: {
        Articles,
      },
      apollo: {
        category: {
          prefetch: true,
          query: articlesQuery,
          variables() {
            return { id: parseInt(this.$route.params.id) };
          },
        },
      },
    };
    </script>

进入全屏模式 退出全屏模式

不要忘记查询!创建一个apollo/queries/article/articles-categories.gql包含以下内容:

    query Category($id: ID!){
      category(id: $id) {
        data {
          attributes {
            name
            articles {
              id
              data {
                attributes {
                  title
                  content
                  image {
                    data {
                      attributes {
                        url
                      }
                    }
                  }
                  category {
                    data {
                      attributes {
                        name
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

进入全屏模式 退出全屏模式

**太棒了!**您现在可以浏览类别:)

结论

非常祝贺,您成功完成了本教程。我希望你喜欢它!

[](https://res.cloudinary.com/practicaldev/image/fetch/s--H-FmCSqZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/http://giphygifs.s3。 amazonaws.com/media/b5LTssxCLpvVe/giphy.gif)

点击这里访问 GitHub 上的源代码。

还是饿?

随意添加其他功能,根据您自己的需要调整此项目,并在评论部分提供您的反馈。

如果要部署应用程序,请查看文档。

[图像描述](https://res.cloudinary.com/practicaldev/image/fetch/s--kVGgUqfR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/tl7jgtavowy04diaq903.jpeg)

Logo

前往低代码交流专区

更多推荐