Вопрос: Как на vuejs преобразовать строку в компонент?

Лучший ответ:
Собственно кусок кода проекта из нашей статьи) https://habr.com/post/414137/<script>
    import {parse} from 'himalaya'
    import Product from '~/components/Product/Product.vue';
    const hasProduct = parsedHtml => {
        let has = false;
        if (parsedHtml.children) {
            parsedHtml.children.forEach(ch => {
                if(has) return;
                if (ch.tagName == 'product') {
                    has = true;
                } else {
                    has = hasProduct(ch);
                }
            });
        }
        return has;
    };
    const toElement = (h, products) => parsedHtml => {
        if (parsedHtml.type == 'Text') {
            return [h('span', {
                domProps: {
                    innerHTML: parsedHtml.content
                },
            })];
        }
        if (parsedHtml.tagName == 'product') {
            let product = products.find(product => product.slug == parsedHtml.attributes.slug);
            if (!product) return '';
            return [h('div', {
                'class': ['catalog', 'catalog_view_row'],
            }, [
                h('div', {
                    'class': ['catalog__cell'],
                }, [
                    h(
                        'product',
                        {props: {product}}
                    )
                ])
            ])];
        }
        let has = hasProduct(parsedHtml);
        return h(
            has ? 'div' : parsedHtml.tagName,
            {
                'class': parsedHtml.attributes.className,
                'attrs': parsedHtml.attributes,
            },
            parsedHtml.children
                ? parsedHtml.children.map(toElement(h, products))
                : []
        )
    };
    export default {
        components: {
            Product,
        },
        props: [
            'html',
            'products',
        ],
        render(h) {
            let tree = parse(`<div>${this.html}</div>`);
            return tree.map(toElement(h, this.products))[0];
        }
    };
</script>
И регулярга:let match = article.content.match(/\$product\[([^\]]+)\]/g);
            if(match != null && match.length) {
                let promises = match.map(async (m) => {
                    let slug = m.match(/\[(.+)\]/)[1];
                    try {
                        let product = await ctx.app.$api.product(slug);
                        if(product) products.push(product);
                    } catch (e) {
                    }
                });
                await Promise.all(promises);
            }

Худший ответ:
Собственно кусок кода проекта из нашей статьи) https://habr.com/post/414137/<script>
    import {parse} from 'himalaya'
    import Product from '~/components/Product/Product.vue';
    const hasProduct = parsedHtml => {
        let has = false;
        if (parsedHtml.children) {
            parsedHtml.children.forEach(ch => {
                if(has) return;
                if (ch.tagName == 'product') {
                    has = true;
                } else {
                    has = hasProduct(ch);
                }
            });
        }
        return has;
    };
    const toElement = (h, products) => parsedHtml => {
        if (parsedHtml.type == 'Text') {
            return [h('span', {
                domProps: {
                    innerHTML: parsedHtml.content
                },
            })];
        }
        if (parsedHtml.tagName == 'product') {
            let product = products.find(product => product.slug == parsedHtml.attributes.slug);
            if (!product) return '';
            return [h('div', {
                'class': ['catalog', 'catalog_view_row'],
            }, [
                h('div', {
                    'class': ['catalog__cell'],
                }, [
                    h(
                        'product',
                        {props: {product}}
                    )
                ])
            ])];
        }
        let has = hasProduct(parsedHtml);
        return h(
            has ? 'div' : parsedHtml.tagName,
            {
                'class': parsedHtml.attributes.className,
                'attrs': parsedHtml.attributes,
            },
            parsedHtml.children
                ? parsedHtml.children.map(toElement(h, products))
                : []
        )
    };
    export default {
        components: {
            Product,
        },
        props: [
            'html',
            'products',
        ],
        render(h) {
            let tree = parse(`<div>${this.html}</div>`);
            return tree.map(toElement(h, this.products))[0];
        }
    };
</script>
И регулярга:let match = article.content.match(/\$product\[([^\]]+)\]/g);
            if(match != null && match.length) {
                let promises = match.map(async (m) => {
                    let slug = m.match(/\[(.+)\]/)[1];
                    try {
                        let product = await ctx.app.$api.product(slug);
                        if(product) products.push(product);
                    } catch (e) {
                    }
                });
                await Promise.all(promises);
            }