If you have dreams and dry goods, you can search for [Great Move to the World] on WeChat and pay attention to this Shawanzhi who is still washing dishes in the early hours of the morning.
This article GitHub https://github.com/qq449245884/xiaozhi has been included, there are complete test sites, materials and my series of articles for interviews with first-line manufacturers.
Composability is by far the best way to organize business logic in a Vue 3 app.
They let you extract small pieces of logic into functions that we can reuse easily, making code easier to write and read.
Since this way of writing Vue code is relatively new, you might be wondering what the best practices are when writing composable code. This series of tutorials will serve as a guide on how to write trustworthy and reliable composable code.
Here's what we'll discuss.
- How to use options object parameters to make composition more configurable
- Using ref and unref to make our arguments more flexible
- A simple way to make the return value more useful
- Why starting with an interface makes our composition stronger
- How to use async code that doesn't require await -- making your code easier to understand
First of all, let's not look at what is composable?
What is composable?
According to the Vue documentation, composable is "functions that leverage the Vue Composition API to encapsulate and reuse stateful logic".
This means that any code that uses reactive can be turned into a composable one.
Below is a simple example of useMouse composable from the Vue.js documentation.
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
We define the state as refs
and then update that state when the mouse moves. By returning x
and y
refs, we can use them in any component (even another composable component).
Here's how we can use this composable in a component.
<template>
X: {{ x }} Y: {{ y }}
</template>
<script setup>
import { useMouse } from './useMouse';
const { x, y } = useMouse();
</script>
As you can see, all this logic can be reused using the useMouse
combination. With very little extra code, we can grab the mouse coordinates in our component.
options object parameter
Most composable programs have one or two necessary inputs. Then there is a series of optional parameters to help configure how the composable works.
When configuring your composable, instead of passing in a long list of arguments, you can pass in an options object.
// 使用一个选项对象
const title = useTitle('A new title', { titleTemplate: '>> %s <<' });
// Title is now ">> A new title <<"
// 使用入一长串的参数
const title = useTitle('A new title', '>> %s <<');
// Title is now ">> A new title <<"
Passing options as a whole object instead of parameters gives us some benefits.
First, we don't need to remember the correct order of arguments. Now with TypeScript and editor autocomplete, this is less of an issue, but it still makes a difference. For a Javascript object, the order of keys does not matter.
Second, the code is more readable because we know what this option does. Code is a comment. We don't need to look in the source code, and we don't need to rely on our IDE to let us know.
Third, it's much easier to add new options later. This applies both to adding new options to the composable itself, and to adding options when using the composable.
So, it would be better to use an options object. But how do we achieve it?
implemented in a composable manner
Here's how to implement the options object pattern in a composable.
export function useMouse(options) {
const {
asArray = false,
throttle = false,
} = options;
// ...
};
Here, we can accept one or two parameters if the parameter is required, then the last parameter is the options object. So in this example, useMouse
has no necessary parameters, just options objects.
The next step is to explode the options object. With destructuring, we can access all the values and explicitly provide default values for each possible option.
Now, we'll see how two different combinations in VueUse apply the pattern. VueUse is an open source portfolio collection for Vue 3 that is very well written. It's a great resource for learning how to write composable code
https://vueuse.org/
First, let's see how useTitle
and then useRefHistory
work.
useTitle
useTitle is a fairly simple combination. It is used to update the title of the page.
const title = useTitle('Initial Page Title');
// Title: "Initial Page Title"
title.value = 'New Page Title';
// Title: "New Page Title"
It also has several options for extra flexibility.
A title of titleTemplate
can be provided, which can also be set to observe (using MutationObserver ) any changes other scripts may make.
const titleOptions = {
titleTemplate: '>> %s <<',
observe: true,
};
Here's how to use the options object:
const title = useTitle('Initial Page Title', {
titleTemplate: '>> %s <<',
observe: true,
});
// Title: ">> Initial Page Title <<"
title.value = 'New Page Title';
// Title: ">> New Page Title <<"
When you look at the source of useTitle, it does this:
export function useTitle(newTitle, options) {
const {
document = defaultDocument,
observe = false,
titleTemplate = '%s',
} = options;
// ...
}
useTitle
The composable has a required parameter, followed by a options
object. After that, it implements the rest exactly following the pattern described here.
Now let's look at a slightly more complex composable that also uses this option object pattern.
useRefHistory
useRefHistory
is more interesting. It lets you keep track of all the changes made to a ref
and can easily perform undo and redo operations.
// Set up the count ref and track it
const count = ref(0);
const { undo } = useRefHistory(count);
// Increment the count
count.value++;
// Log out the count, undo, and log again
console.log(counter.value); // 1
undo();
console.log(counter.value); // 0
This combinable can take many different options
{
deep: false,
flush: 'pre',
capacity: -1,
clone: false,
// ...
}
We can further configure this composable behavior by passing in the options object as the second parameter, as in our previous example.
const state = ref({});
const { undo, redo } = useRefHistory(state, {
deep: true, // 追踪对象和数组内部的变化
capacity: 15, // 限制我们追踪的步骤数量
});
If we look at this source code , we will see that it uses the exact same object refactoring pattern as useTitle
.
export function useRefHistory(source, options) {
const {
deep = false,
flush = 'pre',
eventFilter,
} = options;
// ...
}
However, in this example, we're only extracting a few values from the options object at the beginning.
This is because useRefHistory
internally depends on useManualRefHistory
composable program. The rest of the options will be passed in later composables as that composable options object.
// ...
const manualHistory = useManualRefHistory(
source,
{
// Pass along the options object to another composable
...options,
clone: options.clone || deep,
setSource,
},
);
// ...
get everything together
This article is the first in our "Writing Better Portfolios" series.
We looked at how adding an options object as a parameter to a component makes the component much more configurable. For example, you don't need to worry about the ordering of parameters, you don't need to remember what each parameter does, and it's much easier to add more options to an object than to update the parameters passed in.
But we didn't just look at the pattern itself. We also saw how the VueUse compositions useTitle
and useRefHistory
implement this pattern. Their way is slightly different, but since this is a simple pattern, there aren't many changes you can make.
The next article in this series will explore how we accept Refs and regular Javascript values as parameters.
// 传递一个 ref 值,可以工作
const countRef = ref(2);
useCount(countRef);
// 或者只给一个简单的数字
const countRef = useRef(2);
This adds flexibility and allows us to use composition in more situations in our application.
The bugs that may exist in editing cannot be known in real time. In order to solve these bugs afterwards, a lot of time is spent on log debugging. By the way, here is a useful BUG monitoring tool , Fundebug .
Author: Michael Thiessen Translator: Xiaozhi Source: vuemastery
Original: https://www.vuemastery.com/blog/coding-btter-composables-1-of-5
comminicate
If you have dreams and dry goods, you can search for [Great Move to the World] on WeChat and pay attention to this Shawanzhi who is still washing dishes in the early hours of the morning.
This article GitHub https://github.com/qq449245884/xiaozhi has been included, there are complete test sites, materials and my series of articles for interviews with first-line manufacturers.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。