Crear componente vue de forma dinámica

Importar, extender e instanciar

Primero importaremos el componente y crearemos un «extend» del mismo en una variable fuera de la llamada inicial de vue. Esto vale para cualquier tipo de componente que se haya creado. Utilizaré como ejemplo uno que he creado personalizado.

import SelectComponent from './components/SelectComponent.vue'
var SelectComponentClass = Vue.extend(SelectComponent)

En la instanciación raíz de vue, añadiremos en el método correspondiente la instanciación del nuevo componente.

new Vue({
    el: '#configuracion',
    data: {
        options: [],
        selectedOption: null,
    },
    methods: {
        showSelect() {
            var instanceSelect = new SelectComponentClass({
                propsData: {
                    selectId: 'componente-select',
                    selectOptions: this.options,
                    selectedOptionParam: this.selectedOption
                }
            })
            instanceSelect.$mount()
        }
    }
})

Podemos observar que al hacer la llamada a la clase que extiende el componente le pasamos por parámetro un objeto con datos. Esto es porque nuestro componente espera esos mismos parámetros y los aplica en el mismo.

Aplicación en nuestro HTML

Crearemos un elemento nuestro HTML con el que Vue puede interactuar a través del parámetro «ref» y le asignaremos el valor de «select». Si quisieramos añadir un nombre de referencia compuesto, hay que utilizar camelCase para darle ese valor. Por ejemplo «selectComponent». Esto es porque luego en la llamada dentro de nuestro Vue, this.$refs no aceptaría por ejemplo un valor tipo this.$refs.select-component.

<div class="row mb-2">
    <div class="col-lg-12" class="form-group">
        <label class="form-control-label">Select</label>
        <div ref="select"></div>
    </div>
</div>

Añadiremos ahora una nueva línea en nuestro método «showSelect» que realizará la acción de añadir en nuestro HTML el componente. Además utilizaremos el método «mounted» de la instanciación raíz para añadirlo una vez se haya renderizado todos los elementos de nuestro HTML.

new Vue({
    el: '#configuracion',
    data: {
        options: [],
        selectedOption: null,
    },
    mounted() {
        this.showSelect()
    },
    methods: {
        showSelect() {
            var instanceSelect = new SelectComponentClass({
                propsData: {
                    selectId: 'componente-select',
                    selectOptions: this.options,
                    selectedOptionParam: this.selectedOption
                }
            })
            instanceSelect.$mount()
            this.$refs.select.appendChild(instanceSelect)
        }
    }
})