I'm starting to get comfortable with Vue's composition API, but every time I make a composable I ask myself which pattern to use. If I have a composable whose state depends on outside triggers:
- should I return a function from the composable that performs an action on the state? Or
- should I instead let the composable accept a reactive state from outside to update the state managed by the composable?
Scenario: list users
For example, I need to make a composable that fetches a list of users from an API. The list must reactively update when filtered by user name.
Composable pattern 1: return reactive list and action on that list
<script setup lang="ts">
const { list, setList } = useUserList();
</script>
<template>
<pre>{{ list }}</pre>
<button type="button" @click="setList('john')">List users named "John"</button>
</template>
Composable pattern 2: return reactive list based on input reactive dependency
<script setup lang="ts">
const nameFilter = ref('');
const { list } = useUserList(nameFilter);
</script>
<template>
<pre>{{ list }}</pre>
<button type="button" @click="nameFilter = 'John'">List users named "John"</button>
</template>
Which of the two patterns should I do? The example scenario may be simple enough to make the choice negligible, but on more complex logic (e.g., making higher-order composables) I imagine its effect compounding.
I'm starting to get comfortable with Vue's composition API, but every time I make a composable I ask myself which pattern to use. If I have a composable whose state depends on outside triggers:
- should I return a function from the composable that performs an action on the state? Or
- should I instead let the composable accept a reactive state from outside to update the state managed by the composable?
Scenario: list users
For example, I need to make a composable that fetches a list of users from an API. The list must reactively update when filtered by user name.
Composable pattern 1: return reactive list and action on that list
<script setup lang="ts">
const { list, setList } = useUserList();
</script>
<template>
<pre>{{ list }}</pre>
<button type="button" @click="setList('john')">List users named "John"</button>
</template>
Composable pattern 2: return reactive list based on input reactive dependency
<script setup lang="ts">
const nameFilter = ref('');
const { list } = useUserList(nameFilter);
</script>
<template>
<pre>{{ list }}</pre>
<button type="button" @click="nameFilter = 'John'">List users named "John"</button>
</template>
Which of the two patterns should I do? The example scenario may be simple enough to make the choice negligible, but on more complex logic (e.g., making higher-order composables) I imagine its effect compounding.
Share Improve this question edited Mar 13 at 8:47 Christian asked Mar 13 at 8:38 ChristianChristian 8311 gold badge6 silver badges19 bronze badges 2 |1 Answer
Reset to default 0Setter function is generally redundant in Vue because refs are reactive and can be watched. As a rule of thumb, modified pattern 1 is commonly used:
const { list, filter } = useUserList();
If a composable is implemented for team or public usage, then both modified pattern 1 and pattern 2 are applicable. It may be necessary to pass a ref that already exists to a composable.
A universal implementation that allows both uses:
function useUserList(filter = ref()) {
const list = ref();
...
return { list: readonly(list), filter }
}
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744713374a4589473.html
nameFilter
becomes extensive, using Composable Pattern 1 would lead to overly bloated code, in which case I would opt for Composable Pattern 2 or other patterns. – yuanyxh Commented Mar 13 at 8:57nameFilter
ref in pattern 1 then callsetList(nameFilter.value)
every time the ref value changes. – Christian Commented Mar 13 at 9:45