import {defineComponent,createApp} from 'vue'
buttonView = defineComponent({
extends: Button, data() {
return {
type: "1111"
}
}
})
const div = document.createElement('div');
this.$refs.container.appendChild(div);
createApp(buttonView ).mount(div)
Answer from Max on Stack Overflowimport {defineComponent,createApp} from 'vue'
buttonView = defineComponent({
extends: Button, data() {
return {
type: "1111"
}
}
})
const div = document.createElement('div');
this.$refs.container.appendChild(div);
createApp(buttonView ).mount(div)
This works for me, using options API, in a method create a component
import { defineComponent } from "vue";
createComponent() {
var component = {
data() {
return {
hello:'world',
}
},
template:`<div>{{hello}}</div>`
}
var instance = defineComponent(component);
}
Use it within your template once you've instantiated it
<component :is="instance" v-if="instance"/>
Here's how to do with createApp in Vue 3, but the context (stores, plugins, directives...) will not be kept.
Copy// DialogService.js
import { createApp } from 'vue';
export default {
alert(text) {
const mountEl = document.createElement('div');
document.body.appendChild(mountEl);
const dialog = createApp({ extends: DialogComponentDef }, {
// props
text,
// events are passed as props here with on[EventName]
onClose() {
mountEl.parentNode.removeChild(mountEl);
dialog.unmount();
dialog = null;
},
});
dialog.mount(mountEl);
},
};
To keep the context, there's something more complicated that can be seen here with h and render Vue methods : https://github.com/vuejs/vue-next/issues/2097#issuecomment-709860132
I would recommend using the mount-vue-component. It's lightweight and easy to use. Code example:
Copyimport MyComponent1 from './MyComponent1.vue'
import MyComponent2 from './MyComponent2.vue'
import { mount } from 'mount-vue-component'
let dynamicComponent = mount(someCondition ? MyComponent1 : MyComponent2, { props: { <someProperties...> }, app: MyVueApp })
I use Vue3 with Vite.
I have a dozen of components, all defined as SFCs and using the composition API and the script setup syntax. They all look pretty similar to this:
<template>
<p>My component</p>
</template>
<script setup>
const props = defineProps({
propA: {
type: String,
default: ''
}
});
</script>I am trying to create instances of these components, and add them to my app, programmatically. And so far, all the methods I have read about online, fail miserably.
The most promising seem to be the one described in this comment in an issue of the official Vue GitHub. Here is how I implemented it:
var myComponentInstance = defineComponent({
extends: myComponent,
data: () => ({
props: {
propA: 'ABCDE'
}
})
});
createApp(TitleComponent).mount(this.$refs.container);But even though I think I'm doing what's expected, it fails miserably and I get tons of JS errors.
Is there an easy way to create instances of various Components (providing data via props) and mount them in my app, reliably?
I figured how to do it using <component :is="type" /> and wrote this exemple.
I'm porting some old code that is basically this:
import Modal from 'Modal.vue'
import Vue from 'vue'
var ComponentClass = Vue.extend(Modal)
var instance = new ComponentClass({
propsData: { title: 'title' }
})
instance.$mount() // pass nothing
this.$refs.container.appendChild(instance.$el)
I can't seem to find a way to get this working using Vue3.
Vue.extend has been removed, as far as I can see there's now defineComponent, but it does not seem to work the same way.
I get the following error when I just try and replace it 1-1: TypeError: ComponentClass is not a constructor
Has anyone tried something similar, or know how to fix this?
Use createApp instead of Vue.extend
here's a example of simple vue3 components programmatically
import Button from 'Button.vue'
import { createApp } from "vue"
// Creating the Instance
// use createApp https://v3.vuejs.org/api/global-api.html#createapp
var ComponentApp = createApp(Button)
import Button from "./Button.vue"
// inserting to dom
const wrapper = document.createElement("div")
ComponentApp.mount(wrapper)
document.body.appendChild(wrapper)
set props or slot is a little different by use h, https://v3.vuejs.org/api/global-api.html#h
import Button from 'Button.vue'
import { createApp, h } from "vue"
var ComponentApp = createApp({
setup () {
return () => h(Button, {type: "primary"}, "default slot as children")
}
})
If I understood you correctly, then the solution will be like this
You can learn more about 'defineAsyncComponent' on the official website https://v3.vuejs.org/api/global-api.html#defineasynccomponent
<template>
<button @click="addTag()" type="button">Add new tag</button>
<br>
<div>
<div v-for="child in children" :key="child.name">
<component :is="child"></component>
</div>
</div>
</template>
<script>
import { defineAsyncComponent, defineComponent, ref } from "vue"
export default defineComponent({
components: {
UploadTaskTag: defineAsyncComponent(() => import("./UploadTaskTag"))
},
setup() {
const children = ref([])
const addTag = () => {
children.value.push('UploadTaskTag')
console.log(children.value)
}
return {
addTag,
children
}
},
})
</script>