Vue 3 calling method dynamically without 'this'
What problem does this feature solve?
Not being able to dynamically call an exported function from a composable in vue3 anymore.
Tried:
const a = this[props.type](b) // Not available in composition api and must be a local function when used in options api
const a = window[props.type](b) // Not available in vue
const t = props.type
const a = (t) => {
this[props.type](b) // Returns a string
}
const a = sleep.call(b) // Works, but function name is not dynamic
Promise.resolve(a).then((result) => {
return result == result ? result : { error: `${props.type}(${b})` } // Asynchronous call
})
See also https://stackoverflow.com/questions/75258344/vue-3-calling-method-dynamically-without-this
What does the proposed API look like?
Introduce the window object or perhaps a new call function
window["sum"]([1,2]) // Returns 3
call("sum", [1,2]) // Returns 3
You example fels very i complete, also your stackoverflow question has an accepted answer so i dont really get what you are asking for.
One thing i can tell you is that we will definitely not put anything on window
.
It should be quite obvious.
In vue2 it was possible to call a function by arguments.
this[function][arguments] // Only works for local methods and global functions provided by a mixin
In vue3 there is no mixins anymore. There is composables and plugins. Therefore using this
will not work for vue3, also not with the options api unless it's a local method.
The stackoverflow answer only offers a solution for a local method inside a component. I am looking for a solution for calling a global function inside a composable.
If window
is not an option perhaps provide a call
function
Something like
call("sum", [1,2]) // Returns 3
In vue3 there is no mixins anymore. There is composables and plugins. Therefore using this will not work for vue3, also not with the options api unless it's a local method.
There are mixins in Vue 3, but only for Options API, because Composition API + composables is meant to improve on Options API + mixins, where there latter has a multitude of drawbacks.
The stackoverflow answer only offers a solution for a local method inside a component. I am looking for a solution for calling a global function inside a composable.
You can use the same solution for global methods, provided you make those global methods available through a composable (or multiple).
Yes, you will, somewhere, have to create this map object. But that's the way it works with Composition API. It's in places more verbose by design, to be more explicit.
Can you provide an example? I tried many things but I didn't manage to dynamically call a function inside a composable.
// imagine these as globally shared functions that you might have added through a global mixin when using Options API.
export const useSum () => (a, b) => a +b
export const useMultiplication () => (a, b) => a * b
<script setup>
import { useSum, useMultiplication } from '../composables/math.js'
const props = defineProps({
type: String // could be 'sum' | multiply
})
const mathMethods = {
sum: useSum()
multiply: useMultiplication()
}
const callMathMethod(a, b) {
return mathMethods[props.type](a, b)
}
</script>
that whole logic itself could also be extracted into a composable of its own and expose a call function only.
If you need more specific help, visit our discord at chat.vuejs.org or open a thread in this repo's "Discussions" section
@LinusBorg This workaround still requires declaring functions. Why not consider support for this functionality which is also possible with vue2 and js?
The workaround should be without the arguments when declaring the functions. @LinusBorg Can you update?
const mathMethods = {
sum: useSum // Returns the function
multiply: useMultiply() // Returns the result of multiply() instead of the actual function
}
This workaround still requires declaring functions.
Not sure what that means. When you write a mixin, you also have to write the mixin. Here, I write composables instead. Is this about the need to explicitly import and call them? That's kind of the point, being explicit.
Why not consider support for this functionality which is also possible with vue2 and js?
It's still possible in Vue 3 with Mixins and Options API. You have the choice. CompositionAPI hits a different trade-off between explicitness and convenience here - it's a trade-off we made consciously for an overall better code architecture, even if it's a bit cumbersome for this specific usecase. You can accept that tradeoff, or go back to Options API and mixins.
The workaround should be without the arguments when declaring the functions. @LinusBorg Can you update?
Please look at the example again. Each of the composable is a function returning another function that actually takes the arguments. Of course that does not make sense for something as simple as a sum
function (you would probably just import that directly as a utility), but it's the general pattern for composables so I stuck to it here for the example.
I tested it. Your workaround works but you should remove the '()' to return the function instead of the result.
const mathMethods = {
sum: useSum
multiply: useMultiply
}
The feature request is very simple. Provide an object/function to dynamically call a function.
Something like:
call("sum", [1,2]) // Returns 3 from the sum function
If this is not possible I will use the workaround that you provided. I prefer composables over mixins so I will not switch back 2 options api again.
I tested it. Your workaround works but you should remove the '()' to return the function instead of the result.
Nope. If they are composables, they need to be called to get the actual function:
The feature request is very simple. Provide an object/function to dynamically call a function.
It sounds very simple to you, but doesn't fit with the way composition API works, so it's not gonna happen, very likely.
If this is not possible I will use the workaround that you provided.
It would be my recommendation to do that, yes.