组合式函数
“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。
可以更好的复用和改善代码结构
使用异步状态示例进行说明
// fetch.js
import { ref, watchEffect, toValue } from 'vue'
//组合式函数可以接受参数,ref、getter函数都可以
//组合式函数约定用驼峰命名法命名,并以“use”作为开头。
export function useFetch(url) {
const data = ref(null)
const error = ref(null)
const fetchData = () => {
// reset state before fetching..
data.value = null
error.value = null
// 使用toValue函数 如果 url 是一个 ref 或 getter,
// 将返回它的规范化值。
// 否则原样返回。
fetch(toValue(url))
.then((res) => res.json())
.then((json) => (data.value = json))
.catch((err) => (error.value = err))
}
//可以使用`watch()` 显式地监视 ref 或 getter,或者使用 `watchEffect()`
watchEffect(() => {
fetchData()
})
//返回一个包含多个 ref 的普通的非响应式对象,这样该对象在组件中被解构为 ref 之后仍可以保持响应性
return { data, error }
}
在组件中使用的方式如下:
每一个调用 useFetch() 的组件实例会创建其独有的 data、error 状态拷贝,因此他们不会互相影响。
const url = ref('/initial-url')
//data,error是两个ref
const { data, error } = useFetch(url)
// 这将会重新触发 fetch
url.value = '/new-url'
补充一点computed的缓存结果和惰性求值
这是一个useFetch的示例
自定义指令
一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。钩子函数会接收到指令所绑定元素作为其参数。
自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑
在模版中使用
<script setup>
// 在模板中启用 v-focus
const vFocus = {
mounted: (el) => el.focus()
}
</script>
<template>
<input v-focus />
</template>
在组件中使用 始终应用于组件的根节点,和透传 attributes类似,组件有多个根组件时,指令会被忽略并警告,不建议在组件上使用自定义指令
<MyComponent v-demo="test" />
<!-- MyComponent 的模板 -->
<div> <!-- v-demo 指令会被应用在此处 -->
<span>My component content</span>
</div>
全局注册
// 使 v-focus 在所有组件中都可用
app.directive('focus', { /* ... */ })
指令钩子
const myDirective = {
// 在绑定元素的 attribute 前
// 或事件监听器应用前调用
created(el, binding, vnode, prevVnode) {
// 下面会介绍各个参数的细节
},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode, prevVnode) {}
}
钩子参数
-
el:指令绑定到的元素。这可以用于直接操作 DOM。 -
binding:一个对象,包含以下属性。value:传递给指令的值。例如在v-my-directive="1 + 1"中,值是2。oldValue:之前的值,仅在beforeUpdate和updated中可用。无论值是否更改,它都可用。arg:传递给指令的参数 (如果有的话)。例如在v-my-directive:foo中,参数是"foo"。modifiers:一个包含修饰符的对象 (如果有的话)。例如在v-my-directive.foo.bar中,修饰符对象是{ foo: true, bar: true }。instance:使用该指令的组件实例。dir:指令的定义对象。
举例:
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
app.directive('demo', (el, binding) => {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
-
vnode:代表绑定元素的底层 VNode。 -
prevNode:代表之前的渲染中指令所绑定元素的 VNode。仅在beforeUpdate和updated钩子中可用。
简化形式
仅需要在 mounted 和 updated上实现相同的行为
<div v-color="color"></div>
app.directive('color', (el, binding) => {
// 这会在 `mounted` 和 `updated` 时都调用
el.style.color = binding.value
})