# Headless WordPress 与 Nuxt 前端集成及附件处理

URL: https://caijiao.org/posts/21
Source: docs/posts/21.md
Description: 完整指南：使用 WordPress 作为 Headless CMS，Nuxt 作为前端展示，实现文章列表、详情页、封面图及多附件处理方案。

在现代前端开发中，将 WordPress 作为 **Headless CMS** 与 Nuxt 结合，是一种常见的技术方案。本文将系统讲解这种架构，并详细说明 **文章中包含附件时的处理方法**。

## 一、架构思路

### 1. WordPress 作为后端（Headless CMS）

- 仅负责 **内容管理**；
- 通过 **REST API 或 GraphQL** 提供数据；
- 不负责页面渲染。

### 2. Nuxt 作为前端（展示层）

- 渲染页面、输出 [HTML](/html/) 内容、优化 SEO、处理前端交互；
- 从 WordPress 获取数据；
- 支持 **SSR（服务器端渲染）** 或 **SSG（静态生成）**；
- 可部署到 Vercel、Netlify、Cloudflare Pages 等平台。

## 二、WordPress 配置（后端）

### 1. 开启 REST API

WordPress 默认启用 REST API：

````

[https://your-domain.com/wp-json/wp/v2/posts](https://your-domain.com/wp-json/wp/v2/posts)


### 2. 常用数据接口
| 内容类型 | REST API 路径 | 示例 |
|-----------|----------------|------|
| 所有文章 | `/wp-json/wp/v2/posts` | `/wp-json/wp/v2/posts?page=1&per_page=5` |
| 单篇文章 | `/wp-json/wp/v2/posts/:id` | `/wp-json/wp/v2/posts/123` |
| 分类 | `/wp-json/wp/v2/categories` | `/wp-json/wp/v2/categories?slug=news` |
| 页面 | `/wp-json/wp/v2/pages` | `/wp-json/wp/v2/pages?slug=about` |
| 媒体（图片/附件） | `/wp-json/wp/v2/media` | `/wp-json/wp/v2/media/45` |

> ⚠️ 如果跨域访问 Nuxt 前端，需要在 WordPress 配置 CORS 或安装相关插件。

## 三、Nuxt 前端实现

假设使用 **Nuxt 4/3**。

### 1. 安装依赖
```bash
npx nuxi init my-blog
cd my-blog
npm install
````

### 2. 创建 API composable

文件：`composables/useApi.js`

```js
export const useApi = async (endpoint, params = {}) => {
  const baseURL = "https://your-wordpress-site.com/wp-json/wp/v2";
  const url = new URL(`${baseURL}/${endpoint}`);
  Object.entries(params).forEach(([key, value]) =>
    url.searchParams.append(key, value)
  );
  const { data, error } = await useFetch(url.toString());
  if (error.value) throw new Error(error.value);
  return data.value;
};
```

### 3. 获取文章列表

文件：`pages/index.vue`

```vue
<template>
  <div>
    <h1>最新文章</h1>
    <div v-for="post in posts" :key="post.id">
      
    </div>
  </div>
</template>


```

### 4. 获取文章详情

文件：`pages/post/[id].vue`

```vue
<template>
  <article v-if="post">
    <h1 v-html="post.title.rendered"></h1>
    <div v-html="post.content.rendered"></div>
  </article>
</template>


```

## 四、处理文章中的附件

WordPress 的附件是一种 `post_type = attachment`，可分为：

1. **正文中插入的图片或文件**

```html
<p><img src="https://example.com/wp-content/uploads/photo.jpg" /></p>
<p><a href="https://example.com/wp-content/uploads/report.pdf">下载报告</a></p>
```

2. **封面图 / featured_media**
   通过 `featured_media` 字段获取：

```js
let cover = null;
if (post.featured_media) {
  cover = await useApi(`media/${post.featured_media}`);
}
```

3. **自定义字段（ACF 或插件）上传的附件**

```json
{
  "acf": {
    "attachments": [
      { "id": 231, "url": "https://.../file1.pdf" },
      { "id": 232, "url": "https://.../file2.docx" }
    ]
  }
}
```

### Nuxt 前端处理示例

```vue
<template>
  <article>
    <h1 v-html="post.title.rendered"></h1>
    <img v-if="cover" :src="cover.source_url" :alt="cover.title.rendered" />
    <div v-html="fixedContent"></div>

    <ul v-if="post.acf?.attachments">
      <li v-for="f in post.acf.attachments" :key="f.id">
        <a :href="f.url" target="_blank"
          >下载 {{ f.title || f.url.split("/").pop() }}</a
        >
      </li>
    </ul>
  </article>
</template>


```

## 五、推荐最佳实践

| 需求               | 推荐做法                              |
| ------------------ | ------------------------------------- |
| 一般文章（含图片） | 直接渲染 `content.rendered`           |
| 有封面图           | 用 `featured_media` 获取附件详情      |
| 有文件附件         | 在 ACF 或自定义字段中存储文件信息     |
| 跨域资源           | HTML 中替换路径 + nginx 代理 `/media` |
| SEO 优化           | 使用同域名或 CDN 域名资源             |

## 六、参考资料

- [WordPress REST API 官方文档](https://developer.wordpress.org/rest-api/)
- [ACF 插件文档](https://www.advancedcustomfields.com/resources/)
