Subscribe on changes!

app reference per component

avatar
Oct 16th 2020

What problem does this feature solve?

When creating application in Vue 3 using Vue.createApp() that instance is exposing some methods I'd like to access in a particular reference such as app.component() for fetching a registered component's definition for testing, only. (Maybe I've missed the intended way of achieving that.)

I've searched API documentation for a way to access a Vue instance's current application and wasn't successful in this. Either I've missed that part or maybe it isn't as obvious as desired. Thus I'd like to have a vm.$app pointing to the app.

What is intended? We are creating an app which is processing a definition resulting in components compiled on screen. This definition may use simple type names we like to map into components complying with our intended "name space" by means of common prefix to provided components. However, the latter isn't meant to be fixed but may be extended using plugins. At the same time we'd like to permit use of short type names used as well as qualified ones. Thus we need an opportunity to check and optionally qualify the name of a selected component's name to be passed into <component :is="name"> in scope of a component wrapping those selected ones.

<template>
    <component :is="name" v-for="name of components"></component>
</template>

<script>
    export default {
        props: {
            definition: Array,
        },
        computed: {
            components() {
                return this.definition.map( def => {
                    const name = def.type || "default";

                    if ( this.$app.component( name ) ) {
                        return name;
                    }
                    
                    const qualified = `our-prefix-${name}`;
                    if ( this.$app.component( qualified ) ) {
                        return qualified;
                    }
                    
                    return undefined;
                } ).filter( i => i );
            },
        },
    };
</script>

What does the proposed API look like?

vm.$app refers to the application current Vue component instance is related to.

avatar
Oct 16th 2020

@soletan transferred to the correct repository.

You can add this with app.config.globalProperties: https://v3.vuejs.org/api/application-config.html#globalproperties

avatar
Oct 16th 2020

We've found this opportunity for now as well. Thought it might be easier to expose it more generically. However, we are fine with sticking with globalProperties, too.

avatar
Oct 16th 2020

I'd rather not give the impression that it's a good idea to i.e. do app.component('X', X ) somewhere down the tree by actively exposing the app instance in every component.

For most intents and purposes, it will and should only be accessed before mounting.

For edge cases like yours, i feel like app.config.globalProperties or app.provide() is a clean enough way to optionally expose it.

avatar
Oct 16th 2020

I basically second this fear of totally misusing app.component() for declaring new components in an instance and would opt for a different way limited to looking up existing components, only. I also agree this is an edge case and thus consider this opportunity to be some kind of "syntactic sugar" which I see in compliance with the very basic benefit of Vue over competing frameworks such as Angular by providing lots of opportunities with least amount of code required. OTOH it doesn't hurt as much to have this extra reference to application for a start. It doesn't introduce opportunities which aren't available/possible otherwise. And maybe there will be other use cases interested in finding an instance's application for inspection at that level. It's like vm.$el: you shouldn't use it most of the time, maybe stick with declaring a ref or some directive instead ... and still it's there.

UPDATE: I see vm.$app in companionship with vm.$parent and vm.$root ... to examine an instance's context.