面向 WordPress 开发者的 EmDash

本页内容

EmDash 将熟悉的 WordPress 概念——文章、页面、分类法、菜单、小工具和媒体库——带入现代化的 Astro 技术栈。您的内容管理知识可以直接迁移。

保持熟悉的内容

您从 WordPress 了解的概念在 EmDash 中都是一流的功能:

  • Collections 的工作方式类似于自定义文章类型——定义您的内容结构,在模板中查询它
  • 分类法 的工作方式相同——分层(如类别)和扁平(如标签)
  • 菜单 支持拖放排序和嵌套项
  • 小工具区域 用于侧边栏和动态内容区域
  • 媒体库 支持上传、组织和图片管理
  • 管理界面 内容编辑者无需接触代码即可使用

不同的地方

实现方式改变了,但思维模型保持不变:

TypeScript 而非 PHP

模板是 Astro 组件。语法更清晰,但概念相同:输出 HTML 的服务器代码。

内容 API 而非 WP_Query

getEmDashCollection() 这样的查询函数取代了 WP_Query。不需要 SQL,只需函数调用。

基于文件的路由

src/pages/ 中的文件变成 URL。无需记忆重写规则或模板层次结构。

组件而非模板部分

导入并使用组件。与 get_template_part() 相同的想法,更好的组织方式。

快速参考

WordPressEmDash说明
自定义文章类型Collections通过管理界面或 API 定义
WP_QuerygetEmDashCollection()过滤器、限制、分类法查询
get_post()getEmDashEntry()返回条目或 null
类别/标签分类法保留层次结构支持
register_nav_menus()getMenu()一流的菜单支持
register_sidebar()getWidgetArea()一流的小工具区域
bloginfo('name')getSiteSetting("title")网站设置 API
the_content()<PortableText />结构化内容渲染
短代码Portable Text 块自定义组件
add_action/filter()插件钩子content:beforeSave
wp_optionsctx.kv键值存储
主题目录src/ 目录组件、布局、页面
functions.phpastro.config.mjs + EmDash 配置构建和运行时配置

内容 API

查询 Collections

WordPress 查询使用 WP_Query 或辅助函数。EmDash 使用类型化的查询函数。

WordPress

<?php
$posts = new WP_Query([
  'post_type' => 'post',
  'posts_per_page' => 10,
  'post_status' => 'publish',
  'category_name' => 'news',
]);

while ($posts->have_posts()) :
$posts->the_post();
?>

  <h2><?php the_title(); ?></h2>
  <?php the_excerpt(); ?>
<?php endwhile; ?>

EmDash

---
import { getEmDashCollection } from "emdash";

const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
limit: 10,
where: { category: "news" },
});

---

{posts.map((post) => (

  <article>
    <h2>{post.data.title}</h2>
    <p>{post.data.excerpt}</p>
  </article>
))}

获取单个条目

以下示例通过标识符获取条目并渲染它,在 WordPress 和 EmDash 中:

WordPress

<?php
$post = get_post($id);
?>
<article>
  <h1><?php echo $post->post_title; ?></h1>
  <?php echo apply_filters('the_content', $post->post_content); ?>
</article>

EmDash

---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";

const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);

if (!post) return Astro.redirect("/404");
---

<article>
  <h1>{post.data.title}</h1>
  <PortableText value={post.data.content} />
</article>

模板层次结构

WordPress 使用模板层次结构来选择哪个文件渲染页面。Astro 使用明确的基于文件的路由。

WordPress 模板EmDash 等效项
index.phpsrc/pages/index.astro
single.phpsrc/pages/posts/[slug].astro
single-{type}.phpsrc/pages/{type}/[slug].astro
page.phpsrc/pages/pages/[slug].astro
archive.phpsrc/pages/posts/index.astro
archive-{type}.phpsrc/pages/{type}/index.astro
category.phpsrc/pages/categories/[slug].astro
tag.phpsrc/pages/tags/[slug].astro
search.phpsrc/pages/search.astro
404.phpsrc/pages/404.astro
header.php / footer.phpsrc/layouts/Base.astro
sidebar.phpsrc/components/Sidebar.astro

模板部分 → 组件

WordPress 模板部分变成 Astro 组件:

WordPress

// 在模板中:
get_template_part('template-parts/content', 'post');

// template-parts/content-post.php:

<article class="post">
  <h2><?php the_title(); ?></h2>
  <?php the_excerpt(); ?>
</article>

EmDash

---
const { post } = Astro.props;
---

<article class="post">
	<h2>{post.data.title}</h2>
	<p>{post.data.excerpt}</p>
</article>

下面的页面导入该组件并为每篇文章渲染它:

---
import PostCard from "../components/PostCard.astro";
import { getEmDashCollection } from "emdash";

const { entries: posts } = await getEmDashCollection("posts");
---

{posts.map((post) => <PostCard {post} />)}

菜单

EmDash 拥有自动 URL 解析的一流菜单支持:

WordPress

<?php
wp_nav_menu([
  'theme_location' => 'primary',
  'container' => 'nav',
]);
?>

EmDash

---
import { getMenu } from "emdash";

const menu = await getMenu("primary");
---

<nav>
  <ul>
    {menu?.items.map((item) => (
      <li>
        <a href={item.url}>{item.label}</a>
      </li>
    ))}
  </ul>
</nav>

菜单通过管理界面、种子文件或 WordPress 导入创建。

小工具区域

小工具区域的工作方式类似于 WordPress 中的侧边栏:

WordPress

<?php if (is_active_sidebar('sidebar-1')) : ?>
  <aside>
    <?php dynamic_sidebar('sidebar-1'); ?>
  </aside>
<?php endif; ?>

EmDash

---
import { getWidgetArea } from "emdash";
import { PortableText } from "emdash/ui";

const sidebar = await getWidgetArea("sidebar");
---

{sidebar && (

  <aside>
    {sidebar.widgets.map((widget) => {
      if (widget.type === "content") {
        return <PortableText value={widget.content} />;
      }
      // 处理其他小工具类型
    })}
  </aside>
)}

网站设置

网站选项和自定义器设置映射到 getSiteSetting()

WordPressEmDash
bloginfo('name')getSiteSetting("title")
bloginfo('description')getSiteSetting("tagline")
get_custom_logo()getSiteSetting("logo")
get_option('date_format')getSiteSetting("dateFormat")
home_url()Astro.site

下面的示例使用 getSiteSetting() 读取单个设置:

import { getSiteSetting } from "emdash";

const title = await getSiteSetting("title");
const logo = await getSiteSetting("logo"); // 返回 { mediaId, alt, url }

分类法

分类法在概念上的工作方式相同——分层(如类别)或扁平(如标签):

import { getTaxonomyTerms, getEntryTerms, getTerm } from "emdash";

// 获取所有类别
const categories = await getTaxonomyTerms("categories");

// 获取特定术语
const news = await getTerm("categories", "news");

// 获取文章的术语
const postCategories = await getEntryTerms("posts", postId, "categories");

钩子 → 插件系统

WordPress 钩子(add_actionadd_filter)变成 EmDash 插件钩子:

WordPress 钩子EmDash 钩子目的
save_postcontent:beforeSave在保存前修改内容
the_contentPortableText 组件转换渲染的内容
pre_get_posts查询选项过滤查询
wp_head布局 <head>添加 head 内容
wp_footer布局 </body> 之前添加 footer 内容

EmDash 的优势

类型安全

全面使用 TypeScript。Collections、查询和组件都是完全类型化的,因此字段名称和 返回类型可以自动完成并在构建时检查。

性能

默认静态生成,需要时进行服务器渲染。支持边缘部署。

现代开发体验

热模块替换。基于组件的架构。现代工具(Vite、TypeScript、ESLint)。

基于 Git 的部署

代码和模板存储在 git 中;内容存储在数据库中。通过推送代码进行部署。

预览链接

EmDash 使用 HMAC 签名令牌生成安全的预览 URL。内容编辑者共享预览链接以显示草稿,以便审核者可以在不登录生产环境的情况下查看。

隔离的插件

EmDash 插件在具有明确 API 的隔离上下文中运行。每个插件只能访问它声明的 API,因此插件不会共享或覆盖彼此的全局状态。

内容编辑者体验

内容编辑者使用类似于 wp-admin 的 EmDash 管理面板:

  • 带有最近活动的仪表板
  • 带有搜索、过滤和批量操作的 Collection 列表
  • 用于内容的富文本编辑器(Portable Text,而非 Gutenberg)
  • 支持拖放上传的媒体库
  • 支持拖放排序的菜单构建器
  • 用于侧边栏内容的小工具区域编辑器

编辑体验很熟悉。底层技术是现代化的。

迁移路径

EmDash 直接导入 WordPress 内容:

  1. 从 WordPress 导出(工具 → 导出)
  2. 在 EmDash 的管理界面中上传 .xml 文件
  3. 将文章类型映射到 Collections
  4. 导入内容和媒体

文章、页面、分类法、菜单和媒体都会转移。Gutenberg 块转换为 Portable Text。自定义字段被分析和映射。

查看 WordPress 迁移指南获取完整说明。

下一步