[Vuejs]-Replace data text with components in Vue 3

2👍

Not sure if this is clean but it should do what you require – sorry, composition API, but it’s so simple its trivial to convert to Options API

const { createApp, ref, computed } = Vue;

createApp({
    setup() {
        const data = ref("Lorem {ipsum} dolor sit amet, consectetur {adipiscing} elit, sed do eiusmod tempor incididunt");
        const magic = computed(() => data.value.split('}').map(v => v.split('{')));
        return { data, magic };
    }
}).mount('#app');
.this.would.be.your.component.rather.than.a.span {
  background-color :#ffdddd;
}
<script src="https://unpkg.com/vue@next"></script>

<div id="app">
  <span v-for="([text, tag], i) in magic" :key="i">
    <span v-if="text.length">{{ text }}</span>
    <span class="this would be your component rather than a span" v-if="tag?.length" :title="`this is tag: ${tag}`">{{ tag }}</span>
  </span>
</div>

1👍

v-html interprets text as raw html, without doing any data binding, meaning it doesn’t create any components. Maybe you want dynamic components instead?

On the topic at hand, if you want to highlight some matched text, I did it this way by using a mark html tag

const highlightText = (word: string, search: RegExp): string => {
  return word.replace(search, function (matchedText) {
    return '<mark class="highlight">' + matchedText + '</mark>';
  });
};

And in template, I used v-html on object’s field.

<span v-if="isHighlighted" v-html="object.text"></span>
<span v-else>{{ object.text }}</span>

Now, in your case, you could go over your text, create a new object for each word with a boolean flag that indicates whether the word should be highlighted or not, and based on that iterate through that list with v-for directive, if it should be highlighted, use MyComponent otherwise use a span.

<div v-for="(word, index) in words" :key="index">
    <MyComponent v-if="word.isHighlighted" :data="word.text" />
    <span v-else>{{ word.text }}</span>
</div>

Resources:

Leave a comment