Composition-api: Document that onMounted sets `this`

Created on 19 Dec 2019  路  5Comments  路  Source: vuejs/composition-api

On Reddit, a question came up about how to do this.$on(event, cb); using the composition API. It had me scratching my head for a long time, but eventually I found out that onMounted if called with a function (not an arrow func) will set this to the component instance, at which point you can just call this.$on as usual.

I think that

a) the fact that this is set should be documented if intended or removed if not

b) it should be better documented how to add programmatic listeners with the composition API, assuming this is the intended method.

documentation

Most helpful comment

Since version 0.3.3 composition API exposes getCurrentInstance

<template>
    <div>
        <span>{{ counter }}</span>
        <button @click="increment">increment</button>
        <button @click="decrement">decrement</button>
    </div>
</template>

<script>
    import Vue from 'vue'
    import VueCompositionApi from '@vue/composition-api'

    Vue.use(VueCompositionApi)

    import { getCurrentInstance } from '@vue/composition-api'

    function useEvents () {
        const vm = getCurrentInstance()

        return {
            on: (event, callback) => vm.$on(event, callback),
            once: (event, callback) => vm.$once(event, callback),
            off: (event, callback) => vm.$off(event, callback),
            emit: (event, ...args) => vm.$emit(event, ...args)
        }
    }

    import { ref } from '@vue/composition-api'

    export default {
        setup () {
            const counter = ref(0)
            const { on, emit } = useEvents()

            on('increment', () => {
                counter.value = counter.value + 1
            })

            on('decrement', () => {
                counter.value = counter.value - 1
            })

            return {
                counter,
                increment () {
                    emit('increment')
                },
                decrement () {
                    emit('decrement')
                }
            }
        }
    }
</script>

All 5 comments

@carlmjohnson thanks for the workaround! Was scratching my head over this one as well. It doesn't feel right using this in the context of the composition api. Would be great to get clarification if this is the intended way of adding listeners programatically 馃

Since version 0.3.3 composition API exposes getCurrentInstance

<template>
    <div>
        <span>{{ counter }}</span>
        <button @click="increment">increment</button>
        <button @click="decrement">decrement</button>
    </div>
</template>

<script>
    import Vue from 'vue'
    import VueCompositionApi from '@vue/composition-api'

    Vue.use(VueCompositionApi)

    import { getCurrentInstance } from '@vue/composition-api'

    function useEvents () {
        const vm = getCurrentInstance()

        return {
            on: (event, callback) => vm.$on(event, callback),
            once: (event, callback) => vm.$once(event, callback),
            off: (event, callback) => vm.$off(event, callback),
            emit: (event, ...args) => vm.$emit(event, ...args)
        }
    }

    import { ref } from '@vue/composition-api'

    export default {
        setup () {
            const counter = ref(0)
            const { on, emit } = useEvents()

            on('increment', () => {
                counter.value = counter.value + 1
            })

            on('decrement', () => {
                counter.value = counter.value - 1
            })

            return {
                counter,
                increment () {
                    emit('increment')
                },
                decrement () {
                    emit('decrement')
                }
            }
        }
    }
</script>

@carlmjohnson - a few things from the referenced PR

  • onMounted setting this is not behavior per spec - technically a bug.
  • getCurrentInstance hasn't landed as a decided part of the API, so that's why it's not documented.
  • this.$on has been removed in Vue 3
  • this is undefined on lifecycle functions
  • getCurrentInstance is part of the API
  • this.$on is replaced with:
setup(_, ctx){
 ctx.emit('change', 1)
}

I'm going to close this issue, if still more questions, please reopen or create another issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ycmjason picture ycmjason  路  5Comments

zzachattack2 picture zzachattack2  路  3Comments

sseeland picture sseeland  路  4Comments

tomlla picture tomlla  路  6Comments

banricho picture banricho  路  3Comments