Use old instance properties in Composition API in Vue.js 3

In the last tip "Easily switch to Composition API in Vue.js 3" I explained how to migrate the basic parts of a Vue.js Object API component to the new Composition API.

However, that's not all. What happens with all instance properties we used to have, such as this.$emit, this.$slots, this.$attrs and so? They were on the this component instance, but there is no this in Composition API.

In the same line, in the last tip I didn't use props, and you used to access them via this in the component instance. How the heck can you access it now?

The thing is, I haven't explained the arguments of the setup function when using Composition API.

Effectively, the first parameter of the setup function receives all the component properties. Following the example from the last tip, let's add two properties to use as the initial values for the money and delta local state variables:

export default {
  props: {
    money: {
      type: Number,
      default: 10
    },
    delta: {
      type: Number,
      default: 1
    }
  },
  setup(props) {
    const money = ref(props.money);
    const delta = ref(props.delta);

    // ...
  }
};

Easy-peasy. Nothing else changes about props management aside from this in Vue.js components.

Now, what about all other instance properties and methods, such as $emit? You can find them in the second argument of the setup function: the setup context object.

The setup context has the following shape:

interface SetupContext {
  readonly attrs: Record<string, string>;
  readonly slots: { [key: string]: (...args: any[]) => VNode[] };
  readonly parent: ComponentInstance | null;
  readonly root: ComponentInstance;
  readonly listeners: { [key: string]: Function };
  emit(event: string, ...args: any[]): void;
}

And what's even cooler, it's that we can use object destructuring on the setup context and the reactivity is not lost!

To illustrate it, I'm going to modify the last example and add some logging in the onMounted hook as well as emitting a money-changed event when that changes:

setup(props, { emit, attrs, slots }) {
    // State
    const money = ref(props.money);
    const delta = ref(props.delta);

    // Hooks
    onMounted(() => {
      console.log("Money Counter (attrs): ", attrs);
      console.log("Money Counter (slots): ", slots);
    });

    // Watchers
    const moneyWatch = watch(money, (newVal, oldVal) =>
      emit("money-changed", newVal)
    );
}

That's it! Now you're already able to use most of Vue.js component instance properties and methods.

But probably you've realized not all are in the render context... What about this.$refs? And plugins that inject stuff such as this.$store?

No worries, I'll cover that in the next tips! No spoilers, stay with me and you'll stay cool!

By the way, if you're a live-coding peep you should check the code from this tip working in this CodeSandbox!

Don't miss out anything about Vue, your favourite framework.

Subscribe to receive all the articles we publish in a concise format, perfect for busy devs.

Related Articles

How to use script setup in Nuxt 2

If you love Vue script setup and want to use it in your current Nuxt 2 project, the Nuxt team has made it possible to start using it today!

Paul Melero

Paul Melero

Feb 14, 2022

Use Composition API to easily handle API requests in Vue.js

Not sure how to organize your API client in Vue.js? Learn this simple technique on how to do it using the new Composition API and make it easy.

Carlos Rodrigues

Carlos Rodrigues

Jul 6, 2020

Create a i18n Plugin with Composition API in Vue.js 3

A example on how to use the inject and provide functions to create a i18n plugin using Composition API in Vue.js 3.

Alex Jover Morales

Alex Jover Morales

Feb 17, 2020

Sponsors

VueDose is proudly supported by its sponsors. If you enjoy it, consider supporting it to ensure the project maintainability.

Silver
Learning Partner