@andrei_pro

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

Всем привет. Сайт на фреймворке vuejs, в качестве текстового редактора использую vue-quill-editor.
Ввожу текст (description) с тегами [album_X]
5b5232613387a429182161.png

Затем принимаю данные по ajax и вывожу:
<p v-html="post.description"></p>

Есть компонент ablum.vue который принимает значение album_X и выводит другой html.

Как связать приходящий description с компонентом и вывести другой компонент?
  • Вопрос задан
  • 1141 просмотр
Решения вопроса 1
@dev_family
Собственно кусок кода проекта из нашей статьи) 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);
            }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
На хабре есть статья

Vue нам предоставляет широкие возможности рендеринга компонента с помощью метода render. Сначала ищем все упоминания указателей на компоненты в пришедшем html и получаем по api данные, нужные для отображения этого компонента. Далее разбиваем весь html на дерево. В этом нам помогла библиотека himalaya. И затем собираем обратно html заменяя указатели на уже готовые компоненты.
Ответ написан
Taraflex
@Taraflex
Ищу работу. Контакты в профиле.
Пример с использованием кодогенерации. На выходе имеем строку содержащую замыкание, которое возвращает объект с render функцией и её помощниками.
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)}};
})()`);
}

Дальше думаю понятно.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы