Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue Composition API: Defining emits

When defining custom events Vue encourages us to define emitted events on the component via the emits option:

app.component('custom-form', {
  emits: ['inFocus', 'submit']
})

Using Vue 3's composition API, when a standalone composition function emits custom events, is it possible to define these in the composition function?

like image 512
PeterB Avatar asked Jan 22 '21 11:01

PeterB


People also ask

How do you define props in Vue composition API?

You define a prop named disabled in MyComponent. vue . ... and then add the component like this, passing in disabled . Note that :disabled="true" and just disabled mean the same thing in both cases - when props are defined or not.

What does emit do in VUE JS?

Vue $emit is a function that lets us emit, or send, custom events from a child component to its parent. In a standard Vue flow, it is the best way to trigger certain events.

How do I emit data from Vue?

Emiting via an Event Bus You create an instance of Vue in your main component, then all other components in your application can emit events to it, and use on to react to those events. var bus = new Vue({}); var vm = new Vue({ methods: { changeView() { bus. $emit('ChangeView', e. target.


3 Answers

No, because composition functions are used inside the setup hook which doesn't have access to the other options like methods and emits:

export default defineComponent({
    name: "layout",
    emits: ['showsidebar'],
    setup(props, { emit }) {
        const showSidebar = ref(true);
        const { breakpoints } = useBreakpoint();
        watch(breakpoints, (val) => {
            showSidebar.value = !(val.is === "xs" || val.is === "sm");
            emit('showsidebar',showSidebar.value);
        });
        return {
            showSidebar,
        };
    },
    data() {
        // ...
    },
});

In the example, useBreakpoint offers only some logic that the component could use. If there was a way to define the emits option in the composition function, then the function would always emit the event, even if the function is only used inside the component that defines the handler of the emitted event.

with the new script setup syntax you could do it as follows:

<script setup>
 import { defineEmits,watch,ref } from 'vue'
    
    const emit = defineEmits(['showsidebar'])
    const showSidebar = ref(true);
    const { breakpoints } = useBreakpoint();
    watch(breakpoints, (val) => {
            showSidebar.value = !(val.is === "xs" || val.is === "sm");
            emit('showsidebar',showSidebar.value);
        });
</script>
like image 185
Boussadjra Brahim Avatar answered Oct 22 '22 08:10

Boussadjra Brahim


I did it like this with the script setup syntax:

<script setup>
    import { defineEmits } from 'vue'

    const emit = defineEmits(['close'])

    const handleClose = () => {
        emit('close')
    }
</script>
like image 38
agm1984 Avatar answered Oct 22 '22 07:10

agm1984


If you are using script setup you can use defineEmits which is a compiler macros and you don't have to import it:

<script setup>
const emit = defineEmits(['inFocus', 'submit'])

emit('inFocus')
</script>

You can also use an object syntax, which allows performing events validation:

<script setup>
const emit = defineEmits({
  // No validation
  inFocus: null,

  // Validate submit event
  submit: ({ email, password }) => {
    if (email && password) return true
    else return false
  }
})

function submitForm(email, password) {
  emit('submit', { email, password })
}
</script>

Note: the submit event will be emitted regardless of validation but if the validation doesn't pass, you will get a Vue warning:

[Vue warn]: Invalid event arguments: event validation failed for event "submit".

See it live


Typing with TS:

<script setup lang="ts">
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
</script>
like image 11
Roland Avatar answered Oct 22 '22 06:10

Roland