在 Vue 上的文章正文中插入组件

问题描述 投票:0回答:1

网站位于

Nuxt 3
Vue
。需要将组件插入到文章的 html 中并替换特殊标签。例如,如果文章文本中存在
#GALLERY#
标签,则
<v-gallery/>
组件将嵌入其位置。或者,如果有必要,我可以立即将
<v-gallery/>
组件的代码存储在文章的文本中。但我如何才能让
Vue
将其识别为组件呢?

示例:

<p>...</p>

#GALLERY_1#

<p>...</p>

#GALLERY_2#

我需要绕过所有 html 并将所有出现的某些标签替换为其相应的组件。或者,我可以立即在标记中显示组件的文本:

<p>...</p>

<v-gallery :id="1"/>

<p>...</p>

<v-gallery :id="2"/>

但是我们需要以某种方式强制

Vue
在看到此类标记时连接组件。


在我收到的一个示例中,建议使用特殊分隔符将文本转换为数组(在我的示例中,这是

#
符号)。我设法做到了这一点。但现在下一个问题出现了——如何处理嵌套标签。如果我的特殊标签显示在另一个标签内,则浏览器将在输出应位于其中的组件之前关闭该标签。

这是一个例子:

<article>
  <section>
    #GALLERY#
  </section>
</article>

浏览器将此类标记转换为:

<article>
  <section>  
  </section>
</article>
<v-gallery/>

发生这种情况是因为浏览器将获取我的一段代码(最多

#GALLERY#
)作为
v-html
中的完整文本,并自动关闭其中的所有标签。因此,标记将不正确。有什么办法可以避免这种情况吗?

vue.js nuxt.js vuejs3 nuxtjs3 nuxt3
1个回答
0
投票

您可以使用动态组件。请参阅下面的示例。

脚本设置语法(comosition-api的语法糖):

<script setup>
import { ref, computed } from 'vue';
import VGallery from '@/components/VGallery';

const text = ref('This is amazing photo GALLERY')

const componentName = computed(() => {
  if(text.value.includes('GALLERY')) return 'VGallery'
})
</script>

<template>
  <div>
     <p>{{ text }}</p>
     <Component :is="componentName" />
  </div>
</template>

组合 API

<template>
  <div>
    <p>{{ text }}</p>
    <component :is="componentName" />
  </div>
</template>

<script>
import { ref, computed } from 'vue';
import VGallery from '@/components/VGallery';

export default {
  setup() {
    const text = ref('This is amazing photo GALLERY');

    const componentName = computed(() => {
      if (text.value.includes('GALLERY')) return 'VGallery';
    });

    return {
      text,
      componentName,
    };
  },
};
</script>

选项 API

<template>
  <div>
    <p>{{ text }}</p>
    <component :is="componentName" />
  </div>
</template>

<script>
import VGallery from '@/components/VGallery';

export default {
  data() {
    return {
      text: 'This is amazing photo GALLERY',
    };
  },
  computed: {
    componentName() {
      if (this.text.includes('GALLERY')) return 'VGallery';
    },
  },
};
</script>

© www.soinside.com 2019 - 2024. All rights reserved.