Home > database >  How to fire an $emit event from Vue Composable
How to fire an $emit event from Vue Composable

Time:05-27

I have a vue composable that needs to fire an event. I naively set it up as follows:

*// composable.js*
import { defineEmits } from "vue";

export default function useComposable() {
  // Vars
  let buffer = [];
  let lastKeyTime = Date.now();
  const emit = defineEmits(["updateState"]);

document.addEventListener("keydown", (e) => {
    // code
    emit("updateState", data);
   }

// *App.vue*
<template>
<uses-composables
    v-show="wirtleState.newGame"
    @updateState="initVars"
  ></uses-composables>
</template>
<script setup>
const initVars = (data) => {
//code here

}

// usesComposable.vue
<template>
  <button @click="resetBoard" >Play Again</button>
</template>

<script setup>
import { defineEmits } from "vue";
import useEasterEgg from "@/components/modules/wirdle_helpers/useEasterEgg.js";


useEasterEgg();
</script>

The error I get is "Uncaught TypeError: emit is not a function useEasterEgg.js:30:11

So obviously you can not use defineEmits in a .js file. I dont see anywhere in Vue docs where they specifically use this scenario. I dont see any other way to do this but using $emits but that is invoked in a template which my composable does not have. Any enlightenment much appreciated.

CodePudding user response:

You can't access emit this way, as the doc says : defineProps and defineEmits are compiler macros only usable inside script setup. https://vuejs.org/api/sfc-script-setup.html

I'm not entirely sure of what you are trying to achieve but you can use vue-use composable library to listen to key strokes https://vueuse.org/core/onkeystroke/

Lx4

CodePudding user response:

This question is a bit confusing. What is <uses-composable>? A composable generally is plan js/ts, with no template. If it had a template, it would just be a component. Even if it was a component, which I mean you could turn it into if thats what you wanted, I don't see anything there that suggests that would be a good idea.

So I guess the question is, why would you want to emit an event? If I'm following what you want, you can just do:

// inside useEasterEgg.js
document.addEventListener('keydown', () => {
    // other code
    const data = 'test';
    updateStateCallback(data);
});

function useEasterEgg() {
  function onUpdateState(callback) {
    updateStateCallback = callback;
  }
  
  return {
    onUpdateState,
  }
}


// Put this wherever you want to listen to the event
const { onUpdateState } = useEasterEgg();

onUpdateState(data => console.log(data));

https://jsfiddle.net/tdfu3em1/3/

Alternatively, if you just want access to data, why not make it a ref and just use it where you want:

const data = ref();

document.addEventListener('keydown', () => {
    // other code
    data.value = resultOfOtherCode;
});

function useEasterEgg() {
  return {
    data,
  }
}


// Anywhere you want to use it
const { data } = useEasterEgg();
  • Related