Answer the question
In order to leave comments, you need to log in
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]
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
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>
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);
}
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.
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)}};
})()`);
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question