A
A
andrei_pro2018-07-20 22:09:06
JavaScript
andrei_pro, 2018-07-20 22:09:06

How to convert string to component in vuejs?

Hello. The site is based on the vuejs framework, I use vue-quill-editor as a text editor.
I enter text (description) with tags [album_X]
5b5232613387a429182161.png
Then I receive data via ajax and output: There is an ablum.vue component that takes the album_X value and displays another html. How to bind the incoming description to a component and output another component?
<p v-html="post.description"></p>

Answer the question

In order to leave comments, you need to log in

3 answer(s)
M
Maxim, 2018-07-27
@andrei_pro

Actually a piece of the project code from our article) 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>

And the regular:
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);
            }

V
Vladislav Nagorny, 2018-07-20
@esvils

There is an article on habré

Vue provides us with a wide range of rendering options for the component using the render method. First, we look for all mentions of pointers to components in the incoming html and get the data needed to display this component via api. Next, we split the entire html into a tree. The himalaya library helped us with this. And then we collect the html back by replacing the pointers with ready-made components.

A
Alexander Taratin, 2018-07-21
@Taraflex

An example using code generation. At the output, we have a string containing a closure that returns an object with a render function and its helpers.

import { compile } from 'vue-template-compiler';
import * as transpile from 'vue-template-es2015-compiler';

function toFunction(code) {
    return `(function(){${code}})`;
}

export default () => {
    const vueTemplate = '<div>{{album_1}}</div>'; //тут html для vue шаблона без оборачивания в template
    const { render, staticRenderFns } = compile(vueTemplate, { preserveWhitespace: false });
    return transpile(`(function(){
return {staticRenderFns:[${staticRenderFns.map(toFunction)}],render:${toFunction(render)}};
})()`);
}

Further I think it is clear.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question