启动一个新项目
您是否渴望开始编码? 请按照这些步骤使用 Storyblok 和 Nuxt 启动一个新项目,并在几分钟内开始使用!
终极教程
您是否正在寻找一个动手实践的、循序渐进的教程? Nuxt 终极教程可以满足您的需求!它提供了关于使用 Storyblok 和 Nuxt 从头到尾构建一个完整的多语言网站的全面指导。
安装
安装 @storyblok/nuxt
npx nuxi@latest module add storyblok
将以下代码添加到 nuxt.config.js
的 modules 部分,并将 accessToken 替换为 Storyblok 空间的 API 令牌。
import { defineNuxtConfig } from 'nuxt';
export default defineNuxtConfig({
modules: [
['@storyblok/nuxt', { accessToken: '<your-access-token>' }]
// ...
]
});
如果您愿意,也可以使用 storyblok
配置
import { defineNuxtConfig } from 'nuxt';
export default defineNuxtConfig({
modules: ['@storyblok/nuxt'],
storyblok: {
accessToken: '<your-access-token>'
}
});
警告 此 SDK 在底层使用 Fetch API。如果您的环境不支持,您需要安装一个像 isomorphic-fetch 这样的 polyfill。更多信息请查看 storyblok-js-client 文档。
选项
当您初始化模块时,您可以传递所有 @storyblok/vue 选项,以及一个 bridge
选项(在我们的 JS SDK Storyblok bridge 部分中解释),以及一个 enableSudoMode
选项,用于定义您自己的插件(见下文)。
注意 如果您想在
nuxt-devtools
中使用 Storyblok,您可以使用选项devtools
,如果启用,请确保安装了 @nuxt/devtools 模块并在您的 Nuxt 配置中启用它。
// Defaults
["@storyblok/nuxt", {
{
accessToken: "<your-access-token>",
bridge: true,
devtools: true,
apiOptions: {}, // storyblok-js-client options
}
}]
定义您自己的插件
虽然推荐的方法涵盖了大多数情况,但在某些特定情况下,您可能需要使用 enableSudoMode
选项并禁用我们的插件,从而允许您加入自己的插件。
// nuxt.config.ts
modules: [
[
'@storyblok/nuxt',
{
accessToken: '<your-access-token>',
enableSudoMode: true
}
]
];
要在 SDK 的 apiOptions
中包含其他功能,例如自定义缓存方法,您可以在插件文件夹中(自动导入)实现以下解决方案
// plugins/storyblok.js
import { apiPlugin, StoryblokVue } from '@storyblok/vue';
export default defineNuxtPlugin(({ vueApp }) => {
vueApp.use(StoryblokVue, {
accessToken: '<your-access-token>',
apiOptions: {
cache: {
type: 'custom',
custom: {
flush() {
console.log('all right');
}
}
}
},
use: [apiPlugin]
});
});
区域参数
可能的值
eu
(默认): 用于在欧盟创建的空间us
: 用于在美国创建的空间ap
: 用于在澳大利亚创建的空间ca
: 用于在加拿大创建的空间cn
: 用于在中国创建的空间
在美国创建的空间的完整示例
["@storyblok/nuxt", {
{
accessToken: "<your-access-token>",
apiOptions: {
region: "us"
}
}
}]
重要 对于在美国或中国创建的空间,必须指定
region
参数。
入门
1. 创建您的组件并将它们链接到 Storyblok 可视化编辑器
要将您的 Vue 组件链接到 Storyblok 空间中对应的组件
- 首先,您需要将它们全局加载,将它们添加到
~/storyblok
目录。重要的是在您的代码中使用 Pascal 命名法ExampleComponent.vue
,并在您的 Storyblok 空间中使用连字符example-component
,以便它们被自动导入。
如果您想为 Storyblok 相关组件定义自己的目录,您可以在nuxt.config.js
中使用componentsDir
选项// nuxt.config.ts modules: [ [ "@storyblok/nuxt", { accessToken: "<your-access-token>", componentsDir: '~/components', } ] ], components: { dirs: [ { path: '~/components/storyblok', global: true, } ] },
否则,您可以设置另一个目录并手动加载它们(例如,通过 使用 Nuxt 插件)。警告 请注意,如果您在
storyblok
文件夹中命名一个组件与components
文件夹中的另一个组件相同,它将无法正常工作。提示:保持您的 Nuxt 项目中的组件具有不同的名称。 - 对于每个组件,在其根元素上使用
v-editable
指令,传递它们接收的blok
属性
<div v-editable="blok"></div>
- 最后,使用在 Nuxt 应用中全局可用的
<StoryblokComponent>
<StoryblokComponent :blok="blok" />
blok
是来自 Storblok 的内容交付 API 的实际 blok 数据。
2. 获取 Storyblok Stories 并监听可视化编辑器事件
组合式 API
最简单的方法是使用 useAsyncStoryblok
单行组合式函数(它是自动导入的)。您需要将 slug
作为第一个参数传递,而第二个和第三个参数 apiOptions
和 bridgeOptions
分别是可选的。
请在我们的 API 文档中查看可用的 apiOptions 以及传递给 Storyblok Bridge 的 bridgeOptions。
注意 如果您想了解更多关于版本控制
{ version: "draft" /* 或 "publish" */ }
的信息,请转到 处理预览和/或生产环境 部分
<script setup>
const story = await useAsyncStoryblok(
"vue",
{ version: "draft", resolve_relations: "Article.author" }, // API Options
{ resolveRelations: ["Article.author"], resolveLinks: "url" } // Bridge Options
);
if (story.value.status) {
throw createError({
statusCode: story.value.status,
statusMessage: story.value.response
});
}
</script>
<template>
<StoryblokComponent v-if="story" :blok="story.content" />
</template>
这与分别在 useState
和 useStoryblokBridge
函数中使用 useStoryblokApi
的简写等效
<script setup>
const story = useState();
const storyblokApi = useStoryblokApi();
const { data } = await storyblokApi.get(
`cdn/stories/vue`,
{
version: "draft"
}
);
story.value = data.story;
onMounted(() => {
useStoryblokBridge(
story.value.id,
(evStory) => (story.value = evStory),
{ resolveRelations: ["Article.author"], resolveLinks: "url" } // Bridge Options
);
});
</script>
<template>
<StoryblokComponent v-if="story" :blok="story.content" />
</template>
useState
是一个对 SSR 友好的ref
替代品。它的值将在服务器端渲染之后(在客户端水合期间)保留。
渲染富文本
您可以使用 StoryblokRichText
组件来渲染富文本字段
<template>
<StoryblokRichText :doc="blok.articleContent" />
</template>
或者您可以使用 useStoryblokRichText
组合式函数来获得更多控制
<script setup>
const { render } = useStoryblokRichText({
// options like resolvers
})
const root = () => render(blok.articleContent);
</script>
<template>
<root />
</template>
要了解更多可以传递给 useStoryblokRichText
的强大选项,请查阅 完整选项 文档。
覆盖默认解析器
您可以通过将 resolver
属性传递给 StoryblokRichText
组件来覆盖默认解析器,例如,使用 vue-router 链接或添加自定义 codeblok 组件:
<script setup>
import { NuxtLink } from '#components';
import type { StoryblokRichTextNode } from '@storyblok/vue';
import CodeBlok from "./components/CodeBlok.vue";
const resolvers = {
// NuxtLink example:
[MarkTypes.LINK]: (node: StoryblokRichTextNode<VNode>) =>
h(NuxtLink, {
to: node.attrs?.href,
target: node.attrs?.target,
}, node.text),
// Custom code block component example:
[BlockTypes.CODE_BLOCK]: (node: Node) => {
return h(CodeBlock, {
class: node?.attrs?.class,
}, node.children)
},
}
</script>
<template>
<StoryblokRichText :doc="blok.articleContent" :resolvers="resolvers" />
</template>
如果您想使用 useStoryblokRichText
组合式函数,您可以通过 options 对象传递 resolvers
<script setup>
import CodeBlok from "./components/CodeBlok.vue";
const { render } = useStoryblokRichText({
resolvers: {
// NuxtLink example:
[MarkTypes.LINK]: (node: StoryblokRichTextNode<VNode>) =>
h(NuxtLink, {
to: node.attrs?.href,
target: node.attrs?.target,
}, node.text),
// Custom code block component example:
[BlockTypes.CODE_BLOCK]: (node: Node) =>
h(CodeBlock, {
class: node?.attrs?.class,
}, node.children)
}
});
const root = () => render(blok.articleContent);
</script>
旧版渲染富文本
!警告
旧版richTextResolver
即将弃用。我们建议迁移到上面描述的新方法。
您可以通过使用 @storyblok/nuxt
自带的 renderRichText
函数和一个 Vue 计算属性来轻松渲染富文本
<template>
<div v-html="articleContent"></div>
</template>
<script setup>
const props = defineProps({ blok: Object });
const articleContent = computed(() => renderRichText(props.blok.articleContent));
</script>
您还可以通过将选项作为 renderRichText
函数的第二个参数来设置自定义 Schema 和组件解析器
<script setup>
import cloneDeep from 'clone-deep';
const mySchema = cloneDeep(RichTextSchema); // you can make a copy of the default RichTextSchema
// ... and edit the nodes and marks, or add your own.
// Check the base RichTextSchema source here https://github.com/storyblok/storyblok-js-client/blob/v4/source/schema.js
const props = defineProps({ blok: Object });
const articleContent = computed(() =>
renderRichText(props.blok.articleContent, {
schema: mySchema,
resolver: (component, blok) => {
switch (component) {
case 'my-custom-component':
return `<div class="my-component-class">${blok.text}</div>`;
default:
return 'Resolver not defined';
}
},
}),
);
</script>
3. 处理预览和/或生产环境
请记住,桥接仅在使用 version: 'draft'
和预览访问令牌时有效。
对于生产站点,而不是用作内容编辑器的预览,应使用 version: 'published'
和公共访问令牌。
注意 如果您将生产环境用作营销人员和您的公共站点的预览,您将需要一个插件来处理不同的 .env 变量,或使用预览访问令牌的版本,检查您是否在 Storyblok 内部。例如,类似
if (window.location.search.includes(_storyblok_tk[token]=<YOUR_TOKEN>)
的代码。
请查看官方文档,了解如何访问不同的内容版本。
使用 Nuxt 处理不同内容版本的推荐方法是将环境变量与 Nuxt 运行时配置结合使用,以在您的应用程序中公开配置和密钥
在您的 nuxt.config.ts
中
export default defineNuxtConfig({
runtimeConfig: {
public: {
storyblokVersion: process.env.STORYBLOK_VERSION || 'published'
}
}
});
然后您可以在您的组件中访问运行时配置
const config = useRuntimeConfig();
const story = await useAsyncStoryblok(
'blog',
{
version: config.public.storyblokVersion,
resolve_relations: 'overview.featured_story'
},
{ resolveRelations: 'overview.featured_story' }
);
// or
const { data: articles } = await storyblokApi.get('cdn/stories', {
version: config.public.storyblokVersion,
starts_with: 'blog',
is_startpage: false
});
API
useAsyncStoryblok(slug, apiOptions, bridgeOptions)
(推荐选项)在底层使用 useState
来帮助实现 SSR 兼容性。
请查看可用的 apiOptions(传递给 storyblok-js-client
)和 bridgeOptions(传递给 Storyblok Bridge)。
useStoryblok(slug, apiOptions, bridgeOptions)
当我们需要进行完整的客户端请求时,例如,获取已登录用户的个性化数据时,使用 useStoryblok
代替 useAsyncStoryblok
可能会有所帮助。
请查看可用的 apiOptions(传递给 storyblok-js-client
)和 bridgeOptions(传递给 Storyblok Bridge)。
useStoryblokApi()
返回 storyblok-js-client
的实例。
useStoryblokBridge(storyId, callback, bridgeOptions)
使用此单行函数来覆盖最常见的用例:当 Storyblok 可视化编辑器上发生任何更改时更新 story。
Storyblok JavaScript SDK 生态系统
更多资源
支持
- 错误或功能请求? 提交问题;
- 您对 Storyblok 有疑问或需要帮助吗? 加入我们的 Discord 社区。
贡献
请查看我们的贡献指南和我们的 行为准则。此项目使用 semantic-release 通过使用提交消息生成新版本,我们使用 Angular Convention 来命名提交。请查看 此问题 关于 semantic-release 常见问题解答。