Reputation: 41
I have an #app container with some html, and I create Vue instance on the #app, all the content is compiled and converted to Vuejs components. Then I ajax in another html string, and I need to somehow compile that into components, how do I do that?
Upvotes: 4
Views: 1802
Reputation: 3739
Such thing is not considered a good practice in Vue, but you can actually create components dynamically by using the Vue with template compiler.
Usually, the stand-alone distribution of Vue where you just include a script tag into your page already includes a template compiler.
Upvotes: 0
Reputation: 53350
That is the use case for the template
option, which can either reference to a <template>
with specific ID in your DOM (like you do with your app using the el
option), or directly your HTML template:
Vue.component({
template: `<span class="myItem"><slot></slot></span>`
});
You can easily turn it into an Async Component by providing a function to your component list, which returns a Promise that resolves with the component constructor (e.g. using Vue.extend
):
const MyLoadingComponent = Vue.extend({
template: '#my-loading',
});
new Vue({
el: '#app',
data() {
return {
items: [],
};
},
components: {
'my-component': loadComponentWithLoading,
},
methods: {
addItem() {
this.items.push(Math.random());
},
},
});
// https://v2.vuejs.org/v2/guide/components-dynamic-async.html#Handling-Loading-State
function loadComponentWithLoading() {
return {
component: loadComponent(),
loading: MyLoadingComponent,
};
}
// https://v2.vuejs.org/v2/guide/components-dynamic-async.html#Async-Components
function loadComponent() {
return new Promise(function(resolve, reject) {
loadComponentHtml().then((html) => {
resolve(Vue.extend({
// https://v2.vuejs.org/v2/api/#template
template: html,
}));
});
});
}
function loadComponentHtml() {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(`<span class="myItem"><slot></slot></span>`);
}, 2000);
});
}
.myItem {
color: green;
}
.myLoading {
font-style: italic;
color: red;
}
<script src="https://unpkg.com/vue@2"></script>
<div id="app">
<button @click.prevent="addItem">Add some list items</button>
<ul>
<li v-for="item of items">
<my-component>{{item}}</my-component>
</li>
</ul>
</div>
<template id="my-loading">
<span class="myLoading">Loading…</span>
</template>
Upvotes: 1