Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is "this" undefined in Vue Composition API setup function?

I have a Vue component using v3's composition API:

<template>
  <input type="checkbox" v-model="playing" id="playing" @input="$emit('play', $event.target.value)" />
  <label for="playing" >{{ playing ? 'Pause' : 'Play' }}</label>
</template>
<script>
export default {
  props: {
    done: Boolean
  },
  setup(props) {
    const playing = ref(true)
    watchEvent(() => {
      if (props.done) {
        playing.value = false
        this.$emit('play', playing.value)
      }
    }
    return { playing }
  }
}
</script>

When the watchEvent runs, I get the error Cannot read property "$emit" of undefined. It doesn't look like I'm using the wrong type of function (arrow versus normal function).

It seems like this is undefined throughout setup() regardless of whether it's a function or an arrow function.

like image 926
Ted Morin Avatar asked Mar 03 '23 05:03

Ted Morin


1 Answers

The setup function in the Vue Composition API receives two arguments: props and context.

The second argument provides a context object which exposes a selective list of properties that were previously exposed on this in 2.x APIs:

const MyComponent = {
  setup(props, context) {
    context.attrs // Previously this.$attrs
    context.slots // Previously this.$slots
    context.emit // Previously this.$emit
  }
}

It's important to note that it's not okay to destructure props (you'll lose reactivity), but it's okay to destructure context.

So the code example in the question, use setup(props, { emit }) and then replace this.$emit with emit.

like image 159
Ted Morin Avatar answered Mar 05 '23 16:03

Ted Morin