Vue2结合Sanity.io实现HTML标签包裹指定元素及后续内容
解决方案:Vue2 + Sanity Portable Text 分组渲染为 details/summary
核心思路
由于你使用portable-text-to-vue返回Vue组件块数组,不建议直接操作DOM,而是先对Portable Text原始数据做分组处理,再按分组渲染成details和summary结构。
步骤1:分组处理Portable Text数据
在Vue组件中添加数据分组方法,将以<h1>开头的块和后续关联的<p>块分成独立组:
// Vue组件的methods中定义分组方法 groupBlocksByHeading(blocks) { const groups = []; let currentGroup = null; blocks.forEach(block => { // 匹配Sanity中定义的h1类型(根据你的schema调整_type值) if (block._type === 'h1') { // 保存上一组(如果存在) if (currentGroup) groups.push(currentGroup); // 新建分组,存入当前h1 currentGroup = { heading: block, content: [] }; } // 将后续的p块加入当前分组(同样根据schema调整_type) else if (currentGroup && block._type === 'p') { currentGroup.content.push(block); } }); // 加入最后一组 if (currentGroup) groups.push(currentGroup); return groups; }
通过计算属性处理原始数据:
// Vue组件的computed中 computed: { groupedContent() { // this.sanityBlocks是从Sanity获取的Portable Text原始数据 return this.groupBlocksByHeading(this.sanityBlocks); } }
步骤2:模板中渲染分组内容
利用portable-text-to-vue组件,按分组渲染details和summary结构:
<template> <div class="sanity-content"> <details v-for="(section, idx) in groupedContent" :key="idx" <!-- 可选:默认展开details --> <!-- open --> > <summary> <!-- 渲染分组的h1标题 --> <portable-text :blocks="[section.heading]" /> </summary> <!-- 渲染分组下的所有p内容 --> <portable-text :blocks="section.content" /> </details> </div> </template>
注意事项
- 请根据你的Sanity Schema调整
block._type的判断值(比如部分schema中h1可能是heading1)。 - 如果需要包含其他类型的块(如列表、引用),可扩展
else if的判断条件,将其加入当前分组的content数组。 - 若要自定义
h1或p的渲染样式,可通过portable-text-to-vue的components配置项传入自定义组件。
内容的提问来源于stack exchange,提问作者Mostafa Said
相关产品推荐
相关产品推荐

