You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sanity Studio自定义视图:如何获取引用文档的字段?

如何在Sanity自定义预览视图中展开引用的figure文档字段?

当然可以展开引用并展示对应的资产,核心是要主动获取引用的完整文档数据,而非仅使用默认返回的引用ID。以下是两种可行方案:

方案一:使用useDocument钩子获取引用文档

利用Sanity提供的useDocument钩子,直接通过引用ID拉取完整的figure文档数据:

import React from 'react'
import { useDocument } from '@sanity/react-hooks'

const CampaignBannerPreview = ({ document }) => {
  // 通过引用ID获取figure文档
  const { data: figure, loading } = useDocument(document.image._ref)

  if (loading) return <div>加载中...</div>
  if (!figure) return <div>未选择图片</div>

  // 拼接Sanity图片CDN地址,替换项目ID和数据集
  const imageUrl = figure.image?.asset?._ref 
    ? `https://cdn.sanity.io/images/你的项目ID/你的数据集/${figure.image.asset._ref.split('-')[1]}.${figure.image.asset._ref.split('-')[2]}`
    : ''

  return (
    <div style={{ padding: '2rem' }}>
      <h2>{document.title}</h2>
      <p style={{ margin: '1rem 0' }}>{document.bodyText}</p>
      {imageUrl && (
        <img 
          src={imageUrl} 
          alt={figure.caption || figure.title}
          style={{ maxWidth: '100%', marginBottom: '1rem' }}
        />
      )}
      {figure.caption && <p><em>{figure.caption}</em></p>}
      <a 
        href={document.callToAction.url} 
        style={{ display: 'inline-block', padding: '0.5rem 1rem', background: '#0055cc', color: 'white', textDecoration: 'none' }}
      >
        {document.callToAction.text}
      </a>
    </div>
  )
}

// 在defaultDocumentNodeResolver中注册自定义视图
export default function defaultDocumentNodeResolver(S, { schemaType }) {
  if (schemaType === 'campaignBanner') {
    return S.document().views([
      S.view.form(),
      S.view.component(CampaignBannerPreview).title('横幅预览')
    ])
  }
  return S.document()
}

方案二:使用GROQ查询预展开引用

通过GROQ查询主动指定要展开的引用字段,更灵活地控制返回的数据结构:

import React, { useEffect, useState } from 'react'
import { useClient } from '@sanity/react-hooks'

const CampaignBannerPreview = ({ documentId }) => {
  const client = useClient()
  const [bannerData, setBannerData] = useState(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const fetchFullBannerData = async () => {
      const data = await client.fetch(`
        *[_id == $documentId][0]{
          title,
          bodyText,
          callToAction,
          // 展开figure引用,并进一步展开image的asset
          image->{
            title,
            caption,
            image{
              asset->
            }
          }
        }
      `, { documentId })
      setBannerData(data)
      setLoading(false)
    }
    fetchFullBannerData()
  }, [client, documentId])

  if (loading) return <div>加载中...</div>
  if (!bannerData) return <div>未找到横幅数据</div>

  const imageUrl = bannerData.image?.image?.asset?._id
    ? `https://cdn.sanity.io/images/你的项目ID/你的数据集/${bannerData.image.image.asset._id.split('-')[1]}.${bannerData.image.image.asset._id.split('-')[2]}`
    : ''

  return (
    <div style={{ padding: '2rem' }}>
      <h2>{bannerData.title}</h2>
      <p style={{ margin: '1rem 0' }}>{bannerData.bodyText}</p>
      {imageUrl && (
        <img 
          src={imageUrl} 
          alt={bannerData.image.caption || bannerData.image.title}
          style={{ maxWidth: '100%', marginBottom: '1rem' }}
        />
      )}
      {bannerData.image?.caption && <p><em>{bannerData.image.caption}</em></p>}
      <a 
        href={bannerData.callToAction.url} 
        style={{ display: 'inline-block', padding: '0.5rem 1rem', background: '#0055cc', color: 'white', textDecoration: 'none' }}
      >
        {bannerData.callToAction.text}
      </a>
    </div>
  )
}

// 注册自定义视图
export default function defaultDocumentNodeResolver(S, { schemaType }) {
  if (schemaType === 'campaignBanner') {
    return S.document().views([
      S.view.form(),
      S.view.component(CampaignBannerPreview).title('横幅预览')
    ])
  }
  return S.document()
}

注意事项

  1. 替换代码中的你的项目ID和你的数据集为你Sanity项目的实际信息
  2. 确保已安装@sanity/react-hooks依赖:npm install @sanity/react-hooks
  3. 两种方案都能实现需求,GROQ方案更适合需要精准控制数据字段的场景

内容的提问来源于stack exchange,提问作者Alejandro Aburto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 02:27:52