Reputation: 668
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.
Upvotes: 10
Views: 15584
Reputation: 1376
For Vue 3 Composition API, from the documentation:
...we cannot directly access this.$router or this.$route anymore. Instead we use the useRouter and useRoute functions:
import { useRouter, useRoute } from 'vue-router'
export default {
setup() {
const router = useRouter()
const route = useRoute()
function pushWithQuery(query) {
router.push({
name: 'search',
query: {
...route.query,
...query,
},
})
}
},
}
Upvotes: 0
Reputation: 668
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
.
Upvotes: 16