Vue3集成Payload CMS实时预览方案及Vue友好开源无头CMS推荐
问题1:Vue3集成Payload CMS实时预览功能
1. 完善Payload Pages集合配置
先更新Payload的Pages集合,配置动态预览URL和预览权限:
const Pages = { admin: { useAsTitle: 'title', livePreview: { // 生成带预览路径的URL,编辑时自动打开预览窗口 url: ({ data }) => `http://localhost:1234/preview/${data.slug}`, width: 1200, height: 800 }, }, // 配置预览权限,允许携带预览标识的请求获取草稿数据 access: { preview: ({ req }) => { return req.headers['payload-preview'] || req.query['payload-preview']; }, }, } export default Pages
2. 新增Vue预览路由
修改router/index.js,添加专门的预览路由:
import { createRouter, createWebHistory } from 'vue-router' import Page from '../views/Page.vue' import PreviewPage from '../views/PreviewPage.vue' const routes = [ { path: '/:slug', name: 'Page', component: Page, props: true }, { path: '/preview/:slug', name: 'PreviewPage', component: PreviewPage, props: true } ] const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes }) export default router
3. 实现PreviewPage组件(实时预览核心)
Payload通过WebSocket推送编辑中的草稿数据,组件需要先拉取初始草稿,再监听WebSocket更新:
<template> <div v-if="pageData"> <div v-for="block in pageData.layout" :key="block.id"> <hero-block v-if="block.blockType === 'hero'" :title="block.title" :subtitle="block.content[0]?.children[0]?.text" :imageURL="block.media?.url" :imageAlt="block.media?.['alt text']"> </hero-block> </div> </div> <div v-else> <p>Loading preview...</p> </div> </template> <script> import HeroBlock from '../blocks/HeroBlock.vue' export default { name: 'PreviewPage', components: { HeroBlock }, props: { slug: { type: String, required: true } }, data() { return { pageData: null, socket: null } }, async mounted() { await this.fetchPreviewData() this.connectWebSocket() }, beforeUnmount() { this.socket?.close() }, methods: { async fetchPreviewData() { try { const apiUrl = import.meta.env.VITE_API_URL const response = await fetch(`${apiUrl}/pages?where[slug][equals]=${this.slug}&preview=true`, { headers: { 'Payload-Preview': 'true' } }) if (!response.ok) throw new Error('Failed to fetch preview data') const data = await response.json() this.pageData = data.docs[0] } catch (err) { console.error('Preview data fetch error:', err) } }, connectWebSocket() { const wsUrl = import.meta.env.VITE_API_URL.replace('http', 'ws') + '/ws' this.socket = new WebSocket(wsUrl) this.socket.onopen = () => { this.socket.send(JSON.stringify({ type: 'subscribe', collection: 'pages', id: this.pageData.id })) } this.socket.onmessage = (event) => { const message = JSON.parse(event.data) if (message.type === 'update' && message.collection === 'pages' && message.id === this.pageData.id) { this.pageData = message.doc } } } } } </script>
可选:合并预览与正常页面逻辑
如果不想单独写PreviewPage组件,可在原Page组件中通过路由判断预览模式,合并拉取数据和WebSocket逻辑。
问题2:是否更换CMS?适配Vue的开源无头CMS推荐
不需要因为Payload偏向React就立刻更换,Payload的核心API是框架无关的,仅官方预览组件为React实现,我们完全可以自己写Vue版预览逻辑(如上),如果已经投入配置成本,继续使用是可行的。
如果想换更适配Vue生态的开源无头CMS,推荐:
- Directus:官方用Vue3开发Admin UI,对Vue前端天然友好,支持无代码内容建模、原生实时预览,API自动生成,全开源无商业限制。
- Strapi:最流行的开源无头CMS之一,社区资源丰富,官方提供Vue集成示例,支持REST/GraphQL,自定义能力强,适合大多数Vue项目。
- TinaCMS:轻量级Git-based CMS,适合Nuxt等静态站点,内容直接存储在Git仓库,无需数据库,Vue集成简单。
- KeystoneJS:基于Node.js的高度自定义CMS,支持GraphQL,Vue对接无压力,适合需要复杂后端逻辑的场景。
其中Directus和Strapi是Vue项目的首选,前者对Vue生态适配更自然,后者社区资源更充足。
内容的提问来源于stack exchange,提问作者eligolf
相关产品推荐
相关产品推荐

