Tina支持基于块的编辑,因此您的编辑者可以使用您预定义的块(即页面部分)构建完整的页面。
假设您希望编辑者构建一个页面,并且您有3种主要的“块”类型可以开始:
我们希望允许编辑者在每个页面上使用各种块。
我们将使用object
类型,并提供一个templates
列表,其中每个“模板”代表一个独特的块类型。
import { defineConfig } from 'tinacms';import type { Template } from 'tinacms';const heroBlock: Template = {name: 'hero',label: 'Hero',fields: [{type: 'string',label: '标语',name: 'tagline',},{type: 'string',label: '标题',name: 'headline',},{type: 'string',label: '文本',name: 'text',ui: {component: 'textarea',},},],};const featureBlock: Template = {name: 'features',label: '功能',fields: [{type: 'object',label: '功能项',name: 'items',list: true,fields: [{type: 'string',label: '标题',name: 'title',},{type: 'string',label: '文本',name: 'text',},],},],};const contentBlock: Template = {name: 'content',label: '内容',fields: [{type: 'string',ui: {component: 'textarea',},label: '正文',name: 'body',},],};export default defineConfig({// ...schema: {collections: [{// ...fields: [{type: 'object',list: true,name: 'blocks',label: '部分',templates: [heroBlock, featureBlock, contentBlock],},],},],},});
我们已经定义了3个块(content
、features
、hero
)的结构,以及我们的主要块字段:blocks
。
因为块列表中的每个项目可以有一个独特的模式,查询这些数据不像其他类型的字段那么简单。我们需要使用GraphQL的片段语法来查询每个块类型的适当数据结构。
片段名称是根据集合名称和父字段名称自动生成的。例如,如果集合是pages
,字段是blocks
,块的名称是hero
,则片段将命名为PagesBlocksHero
。
{pages(relativePath: "turbo.json") {blocks {__typename... on PagesBlocksHero {__typenametaglineheadlinetext}... on PagesBlocksFeatures {__typenameitems {titletext}}... on PagesBlocksContent {__typenamebody}}}
{"data": {"pages": {"blocks": [{"__typename": "PagesBlocksHero","tagline": "Turbo means good","headline": "The All-New Turbo Model","text": "Think fast. Think Turbo."},{"__typename": "PagesBlocksFeatures","items": [{"title": "10% Faster","text": "Than our slow one"},{"title": "Safer Than Ever","text": "We settled the lawsuits out of court"}]},{"__typename": "PagesBlocksHero","tagline": null,"headline": "Our Story","text": "Read about the history of Turbo"},{"__typename": "PagesBlocksContent","body": "Lorem ipsum dolor sit amet"}]}}}
有关如何使用Tina的GraphQL API查询数据的更多信息,请查看查询文档
我们可以通过创建一个新的Blocks
组件来渲染页面上的块,该组件将在switch语句中有条件地渲染每种块类型。
// Blocks.tsximport React from 'react';import type { Pages } from '../tina/__generated__/types';import { Content } from './blocks/content';import { Features } from './blocks/features';import { Hero } from './blocks/hero';import { Testimonial } from './blocks/testimonial';export const Blocks = (props: Pages) => {return (<>{props.blocks? props.blocks.map(function (block, i) {switch (block.__typename) {case 'PagesBlocksContent':return (<React.Fragment key={i + block.__typename}><Content data={block} /></React.Fragment>);case 'PagesBlocksHero':return (<React.Fragment key={i + block.__typename}><Hero data={block} /></React.Fragment>);case 'PagesBlocksFeatures':return (<React.Fragment key={i + block.__typename}><Features data={block} /></React.Fragment>);default:return null;}}): null}</>);};
请注意,每个博客上的__typename
是{CollectionName}{FieldName}{BlockTemplateName}
。
在我们的例子中:
这是一个实验性功能,API可能会发生变化。有任何想法吗?请在聊天中告诉我们,或通过我们的社区渠道之一
这个可视化块选择器允许编辑者从一组图像中选择块,而不是文本。
首先,要启用可视化块选择器,UI键中的visualSelector
属性必须设置为true。
...export default defineConfig({// ...schema: {collections: [{// ...fields: [{type: 'object',list: true,name: 'blocks',label: '部分',+ ui: {+ visualSelector: true,+ },templates: [heroBlock, featureBlock, contentBlock],},],},]}})...
要设置块选择器,必须为每个您希望有预览图像的块提供预览图像。每个块的基本结构如下所示。
const featureBlock = {name: 'features',label: '功能',+ ui: {+ previewSrc: "https://...",+ },fields: [{type: 'object',label: '功能项',name: 'items',list: true,fields: [{type: 'string',label: '标题',name: 'title',},{type: 'string',label: '文本',name: 'text',},],},],}
previewSrc
是将在可视化选择器中渲染的图像URL。如果没有提供预览,块仍然可以通过点击标题使用,只是不会显示预览图像。
可选地 可以提供一个category
,允许块分组到不同的类别中。
const featureBlock = {name: 'features',label: '功能',ui: {+ category: "页面部分",previewSrc: "https://...",},fields: [{type: 'object',label: '功能项',name: 'items',list: true,fields: [{type: 'string',label: '标题',name: 'title',},{type: 'string',label: '文本',name: 'text',},],},],}
对于那些喜欢从视频中学习的人,可以查看我们"TinaCMS 深入探讨"系列中的“设置块”片段。