admin管理员组

文章数量:1297256

In vue2 it was be easy:

<template>
 <button :class="type"><slot /></button>
</template>
<script>
 export default {
   name: 'Button',
   props: [ 'type' ],
 }
</script>
import Button from 'Button.vue'
import Vue from 'vue'

var ComponentClass = Vue.extend(Button)
var instance = new ComponentClass()

instance.$mount() // pass nothing
this.$refs.container.appendChild(instance.$el)

extend + create instance. But in vue3 it's has been deleted. Where are another way?

In vue2 it was be easy:

<template>
 <button :class="type"><slot /></button>
</template>
<script>
 export default {
   name: 'Button',
   props: [ 'type' ],
 }
</script>
import Button from 'Button.vue'
import Vue from 'vue'

var ComponentClass = Vue.extend(Button)
var instance = new ComponentClass()

instance.$mount() // pass nothing
this.$refs.container.appendChild(instance.$el)

extend + create instance. But in vue3 it's has been deleted. Where are another way?

Share Improve this question edited Oct 7, 2020 at 20:44 Max asked Oct 7, 2020 at 20:00 MaxMax 4391 gold badge3 silver badges9 bronze badges 2
  • Why are you instantiating components this way (via DOM manipulation) instead of standard Vue idioms (i.e., templates or render functions)? – tony19 Commented Oct 8, 2020 at 3:14
  • 2 @tony19 because it's just an example, real production way wait backend answer and render it with backend data – Max Commented Oct 8, 2020 at 10:58
Add a comment  | 

4 Answers 4

Reset to default 18
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)

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"/>

When I migrated from Element UI to Element Plus I had to pass prefix/suffix icons as components and not as classname strings anymore. But I use single custom icon component and I have to first create a vnode and customize it with props and then pass it in as the icon prop.

So I created a plugin:

import { createVNode, getCurrentInstance } from 'vue'

export const createComponent = (component, props) => {
  try {
    if (component?.constructor === String) {
      const instance = getCurrentInstance()
      return createVNode(instance.appContext.components[component], props)
    } else {
      return createVNode(component, props)
    }
  } catch (err) {
    console.error('Unable to create VNode', component, props, err)
  }
}

export default {
  install(APP) {
    APP.$createComponent = createComponent
    APP.config.globalProperties.$createComponent = createComponent
  }
}

And then I can use it like this for globally registered components:

<component :is="$createComponent('my-global-component', { myProp1: 'myValue1', myProp2: 'myValue2' })" />

And for locally imported components:

<component :is="$createComponent(MyComponent, { foo: 'bar' }) />

Or

data() {
  return {
    customComponent: $createComponent(MyComponent, { foo: 'bar' })
  }
}

<template>
  <component :is="customComponent" />
  <MyOtherComponent :customizedComponent="customComponent" />
</template>

Try out to extend the Button component and then append it root element $el to the referenced container:

import Button from 'Button.vue'


const CompB = {
  extends: Button
}

this.$refs.container.appendChild(CompB.$el)

本文标签: javascriptVue3 Creating Component Instances Programmatically on button clickStack Overflow