十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

TinaCMS Astro 集成如何注册 TinaIsland 添加新的可编辑区域

TinaCMS Astro 集成如何注册 TinaIsland 添加新的可编辑区域 TinaCMS Astro 集成如何注册 TinaIsland 添加新的可编辑区域【免费下载链接】tinacmsTinaCMS is the leading open-source headless CMS that supports Markdown and Visual Editing. Your content is stored in your own GitHub repo ❤️项目地址: https://gitcode.com/GitHub_Trending/ti/tinacms当你已经用tinacms/astro把 TinaCMS 可视编辑接入 Astro 站点并且至少有一个可编辑区域island在正常运行时接下来常见的需求就是再增加一个新的可编辑区域——比如新增一种内容类型的详情页或者把页面上的某个模块单独抽出来让编辑者能点选刷新。这篇基于仓库中tinacms/astro包的 GETTING_STARTED.md 和参考实现examples/astro/visual-editing的正文讲清新增一个 island要改哪几处文件、每处怎么改、改完怎么验证。适用环境Astro 5/6/7、Node 18、TinaCMS 3项目已安装tinacms/astro、tinacms、tinacms/cli和一个 SSR adapter如astrojs/node且astro.config.mjs里已经挂了tina()integration。开始前确认已有基础新增 island 的前提是项目已经走通了集成主路径对应 GETTING_STARTED.md 的第 1–4 步astro.config.mjs中通过integrations: [tina()]引入集成它会自动注入 middleware 并把 vanilla-JS bridge 作为静态文件放在/admin/bridge.js存在src/pages/tina-island/[name].ts这个动态路由且export const prerender false数据加载函数统一用requestWithMetadata()包裹生成的 Tina client 查询否则编辑态下 overlay 数据不会进入渲染。参考实现中的 data.ts 展示了标准写法每个 collection 一个 loader查询走tina/__generated__/clientimport { requestWithMetadata } from tinacms/astro; import client from ../../tina/__generated__/client; export const getPost (slug: string) requestWithMetadata(client.queries.post({ relativePath: ${slug}.md }));如果你要新增的是全新 collection先在tina/collections/配好 collection再用pnpm tinacms init或重建生成客户端如果只是复用已有 collection直接进入下一步。第一步编写区域组件为新的可编辑区域写一个独立的.astro组件接收该区域需要的数据作为 props。参考实现中 islands/ 目录下的PostBody.astro等组件就是这种形态。以 PostBody.astro 为例它做两件事富文本正文用TinaMarkdown渲染注意要从tinacms/astro/TinaMarkdown.astro这个子路径导入裸包的默认导出解析到的是一个占位类型astro check会报Type X is not assignable to type never在想要点击即聚焦的元素上加data-tina-field{tinaField(data, 字段名)}标记--- import TinaMarkdown from tinacms/astro/TinaMarkdown.astro; import { tinaField } from tinacms/astro/tina-field; import type { PostQuery } from ../../../tina/__generated__/types; interface Props { data: NonNullablePostQuery[post]; } const { data } Astro.props; --- {data.title ( h1>import type { IslandRegistry } from tinacms/astro/experimental; import AuthorBody from ../components/islands/AuthorBody.astro; import { getAuthor } from ./data; export const islands: IslandRegistry { // 已有条目page、post、blog、global、global-footer … author: { fetch: (_request, params) getAuthor(params.get(filename) ?? ), component: AuthorBody, wrapper: SECTION_WRAPPER, propsFromData: (data) ({ data: (data as { data?: { author?: unknown } }).data?.author, }), }, };四个字段各自的作用依据 island-route.ts 中的注释fetch: (request, params) Promiseunknown— 解析组件所需数据params是 URL search params可以忽略返回的就是 loader 的结果component— 用取回的数据渲染的 Astro 组件wrapper: { tag; className? }— bridge 替换进 DOM 时套用的外层元素必须与页面侧TinaIsland传入的 wrapper 一致propsFromData: (data, params) props— 把取回的数据和 URL 参数映射为组件 props。新增一个可编辑区域时只需要往这个 map 里加一个条目动态路由会自动按 URL 里的 name 去查表不需要为每个 island 写新路由。第三步在页面里用TinaIsland包裹区域在渲染该区域的页面中引入组件并用TinaIsland包住参考实现 posts/[...urlSegments].astro 的写法--- import TinaIsland from tinacms/astro/TinaIsland.astro; import PostBody from ../../components/islands/PostBody.astro; import { getPost } from ../../lib/data; import { islands } from ../../lib/islands; const slug (Astro.params.urlSegments ?? ).toString(); const post await getPost(slug); if (!post.data?.post) { return new Response(Not Found, { status: 404 }); } const data post.data.post; --- TinaIsland namepost wrapper{islands.post.wrapper} params{{ slug }} primary PostBody data{data} / /TinaIslandTinaIsland的 props见 TinaIsland.astroname— 与 registry 中的 key 一致决定 bridge 去请求哪个/tina-island/[name]端点wrapper— 直接复用islands.xxx.wrapper保证与 registry 条目一致params— 会序列化成 search params 传给fetch和propsFromData例如{ slug }primary— 标记该区域是页面主表单。output: server下可省略第一次requestWithMetadata()调用通常就是页面自己的会被自动视为 primaryoutput: static下必须显式指定否则编辑器的落点可能停在 Referenced Files 列表上。每页最多标一个primary。路由不用动但要保留prerender false动态端点只有一个通用文件 tina-island/[name].ts它通过experimental_createIslandRoute(islands)从注册表取对应条目渲染import type { APIRoute } from astro; import { experimental_createIslandRoute } from tinacms/astro/experimental; import { islands } from ../../lib/islands; export const prerender false; export const ALL: APIRoute experimental_createIslandRoute(islands);新增 island 后这个文件不需要任何改动。唯一要注意的是保持export const prerender false——bridge 对该端点的请求必须由 adapter 按需渲染静态构建下它必须仍然是运行时路由。运行与验证启动命令GETTING_STARTED.md 第 9、10 步pnpm dev # Site: http://localhost:4321/ # Admin: http://localhost:4321/admin/验证方式打开/admin/点进一篇文档编辑某个字段。按文档描述成功时 iframe 只会重新拉取受影响的 island 并把它换进 DOM整页不刷新、页面树里没有 React。针对你新增的区域可以在 DevTools 里进一步确认打开该页面后查看head编辑模式下应包含div contenteditable="false">【免费下载链接】tinacmsTinaCMS is the leading open-source headless CMS that supports Markdown and Visual Editing. Your content is stored in your own GitHub repo ❤️项目地址: https://gitcode.com/GitHub_Trending/ti/tinacms创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表