在本章节我们来了解一下 Composables 在项目开发中的作用及如何使用。Composables是一种利用 Vue 的组合 API 来封装和重用有状态逻辑的函数。在构建前端应用程序时,我们经常需要为常见任务重用逻辑,所以我们为此提取了一个可重用的函数。这个格式化函数封装了无状态逻辑:它接受一些输入并立即返回预期的输出。有许多库可用于重用无状态逻辑 - 例如 lodash 和 date-fns 。
<script setup lang='ts'>
/*
* 佛曰:
* 写字楼里写字间,写字间里程序员;
* 程序人员写程序,又拿程序换酒钱。
* 酒醒只在网上坐,酒醉还来网下眠;
* 酒醉酒醒日复日,网上网下年复年。
* 但愿老死电脑间,不愿鞠躬老板前;
* 奔驰宝马贵者趣,公交自行程序员。
* 别人笑我忒疯癫,我笑自己命太贱;
* 不见满街漂亮妹,哪个归得程序员?
*
* @Description: 布局组件
* @version:1.2.0
* @Date: 2022-09-14 17:55:25
* @Author: wenBin
*/
/****
* Nuxt3组合API
* prefetchComponents
* preloadComponents
* setPageLayout
* etResponseStatus
* updateAppConfig
* useAppConfig
* useAsyncData
* useCookie
* useError
* useFetch
* useHead、
* useNuxtApp
* useRequestHeaders
* useRouter
* useRuntimeConfig
* useState
*
*****/
</script>
1、prefetchComponents可以对预取组件进行控制
使用prefetchComponents手动预取已在 Nuxt 应用程序中全局注册的各个组件。例如:
await prefetchComponents('MyGlobalComponent')
await prefetchComponents(['MyGlobalComponent1', 'MyGlobalComponent2'])
2、preloadComponents可以对预加载组件进行控制
使用preloadComponents手动预取已在 Nuxt 应用程序中全局注册的各个组件。例如:
await preloadComponents('MyGlobalComponent')
await preloadComponents(['MyGlobalComponent1', 'MyGlobalComponent2'])
3、setPageLayout允许动态更改页面的布局。它依赖于对 Nuxt 上下文的访问,并且只能在组件的设置函数、插件和路由中间件中调用。例如
export default defineNuxtRouteMiddleware((to) => {
setPageLayout('other')
})
4、setResponseStatus 设置响应状态
您可以使用setResponseStatus设置响应的 statusCode(以及可选的 statusMessage)。
setResponseStatus只能在组件设置函数、插件和路由中间件中调用。例如:
// 404状态
setResponseStatus(404)
//or
setResponseStatus(404, 'Page Not Found') // 设置状态信息
5、 updateAppConfig更新配置,现有属性被保留。例如:
const appConfig = useAppConfig() // { foo: 'bar' }
const newAppConfig = { foo: 'baz' }
updateAppConfig(newAppConfig)
console.log(appConfig) // { foo: 'baz' }
6、useAppConfig访问配置。例如:
const appConfig = useAppConfig()
console.log(appConfig)
7、 useAsyncData访问异步数据。例如
function useAsyncData(
handler: (nuxtApp?: NuxtApp) => Promise<DataT>,
options?: AsyncDataOptions<DataT>
): AsyncData<DataT>
function useAsyncData(
key: string, //唯一键
handler: (nuxtApp?: NuxtApp) => Promise<DataT>, //返回值异步函数
options?: AsyncDataOptions<DataT>
): Promise<AsyncData<DataT>>
type AsyncDataOptions<DataT> = {
server?: boolean, //是否获取服务器上的数据
lazy?: boolean, //默认false,获取数据之前是否阻塞路由
/**
*
* default异步函数解析之前设置数据默认值的工厂函数 - 特别适用于该`lazy: true`选项
*
****/
default?: () => DataT | Ref<DataT> | null,
transform?: (input: DataT) => DataT, // 可用于`handler`在解析后更改函数结果 的函数
pick?: string[], //只从函数结果 中选择这个数组中的指定键
watch?: WatchSource[], //自动刷新
initialCache?: boolean, //是否跳过有效负载缓存以进行初始提取,默认false
immediate?: boolean //阻止请求立即触发,默认true
}
interface RefreshOptions {
_initial?: boolean
}
type AsyncData<DataT, ErrorT> = {
data: Ref<DataT | null>, //传递参数
pending: Ref<boolean>, //是否仍在获取数据,booolean
execute: () => Promise<void>, //刷新`handler`函数 返回的数据 , fun
refresh: (opts?: RefreshOptions) => Promise<void>,//刷新`handler`函数 返回的数据, fun
error: Ref<ErrorT | null> //数据获取失败时的错误对象
}
//使用
const { data, pending, error, refresh } = await useAsyncData(
'mountains',
() => $fetch('https://api.nuxtjs.dev/mountains')
)
8、useCookie读写 cookie。例如:
const cookie = useCookie(name, options)
//使用
<template>
<div>
<h1> Counter: {{ counter || '-' }}</h1>
<button @click="counter = null">
reset
</button>
<button @click="counter--">
-
</button>
<button @click="counter++">
+
</button>
</div>
</template>
<script setup>
const counter = useCookie('counter')
//如果 cookie 不存在,则最初将其设置为随机值
counter.value = counter.value || Math.round(Math.random() * 1000)
</script>
9、 useError捕获全局错误。例如:
const error = useError()
10、useFetch 获取数据
这个可组合提供了一个方便的包装器useAsyncData和$fetch. 它会根据 URL 和 fetch 选项自动生成密钥,根据服务器路由为请求 url 提供类型提示,并推断 API 响应类型。
//类型
function useFetch(
url: string | Request | Ref<string | Request> | () => string | Request, //要获取的 URL
options?: UseFetchOptions<DataT> //可选参数
): Promise<AsyncData<DataT>>
type UseFetchOptions = {
key?: string, //唯一的key,
method?: string, //请求方法
params?: SearchParams, //查询参数
body?: RequestInit['body'] | Record<string, any>, //请求正文 - 自动字符串化(如果传递了一个对象)
headers?: { key: string, value: string }[], //请求标头
baseURL?: string, //请求的基本 URL
server?: boolean, //是否获取服务器上的数据
lazy?: boolean, ////默认false,获取数据之前是否阻塞路由
immediate?: boolean, //当设置为 时`false`,将阻止请求立即触发。默认true
/**
*
* default异步函数解析之前设置数据默认值的工厂函数 - 特别适用于该`lazy: true`选项
*
****/
default?: () => DataT,
transform?: (input: DataT) => DataT, //解析后 可用于改变函数结果的函数
pick?: string[], //仅从`handler`函数结果中选择此数组中的指定键
watch?: WatchSource[], //自动刷新
initialCache?: boolean //当设置为 时`false`,将跳过有效负载缓存以获取初始数据
}
type AsyncData<DataT> = {
data: Ref<DataT>, //传入参数
pending: Ref<boolean>, //布尔值,指示是否仍在获取数据
refresh: () => Promise<void>, //一个函数,可以用来刷新`handler`函数返回的数据
execute: () => Promise<void>, //一个函数,可以用来刷新`handler`函数返回的数据
error: Ref<Error | boolean> //一个函数,可以用来刷新`handler`函数返回的数据
}
//例如:
const { data, pending, error, refresh } = await useFetch('https://api.nuxtjs.dev/mountains',{
pick: ['title']
})
//使用拦截器
const { data, pending, error, refresh } = await useFetch('/api/auth/login', {
onRequest({ request, options }) {
// 设置请求头
options.headers = options.headers || {}
options.headers.authorization = '...'
},
onRequestError({ request, options, error }) {
// 请求数据错误回调
},
onResponse({ request, response, options }) {
// 获取响应数据回调
return response._data
},
onResponseError({ request, response, options }) {
//返回响应数据数据错误回调
}
})
11、 useHead添加自定义各个页面的头部属性。具体如下:
//类型
useHead(meta: Computable<MetaObject>): void
interface MetaObject extends Record<string, any> {
charset?: string, //文档的字符编码。
viewport?: string, //配置视口
meta?: Array<Record<string, any>>, //**默认值**:`width=device-width, initial-scale=1`
link?: Array<Record<string, any>>, //<link>标签
style?: Array<Record<string, any>>, //<style>标签
script?: Array<Record<string, any>>, //<script>标签
noscript?: Array<Record<string, any>>, //<noscript>标签
titleTemplate?: string | ((title: string) => string), //配置动态模板以自定义单个页面上的页面标题
title?: string, //单个页面上设置静态页面标题
bodyAttrs?: Record<string, any>, //<body>
htmlAttrs?: Record<string, any> // <html>
}
//使用方法
//自定义元素
<script setup lang = 'ts'>
const title = ref('My App')
const description = ref('My amazing Nuxt app')
useHead({
title,
meta: [
{
name: 'description',
content: description
}
]
})
</script>
//动态标题
<script setup lang = 'ts'>
/****
*
*`titleTemplate`设置为带有`%s`占位符的字符串或设置为`function`。
* 注意:nuxt.config中只能设置静态属性
*
*****/
useHead({
// 字符串,
// where `%s` is replaced with the title
titleTemplate: '%s - Site Title',
// 函数
titleTemplate: (productCategory) => {
return productCategory
? `${productCategory} - Site Title`
: 'Site Title'
}
})
</script>
//添加外部CSS
<script setup lang = 'ts'>
useHead({
link: [
{
rel: 'preconnect',
href: 'https://fonts.googleapis.com'
},
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap',
crossorigin: ''
}
]
})
</script>
//添加第三方脚本
<script setup lang = 'ts'>
useHead({
script: [
{
src: 'https://third-party-script.com',
body: true
}
]
})
</script>
12、useNuxtApp获取上下文的方法,它在客户端和服务器端都可用。可以使用这些属性来扩展和自定义您的应用程序以及共享状态、数据和变量。例如:
<script setup lang = 'ts'>
const nuxtApp = useNuxtApp()
//方法
//1、通过 provide(name,value) 创建插件
const nuxtApp = useNuxtApp()
nuxtApp.provide('hello', (name) => `Hello ${name}!`)
console.log(nuxtApp.$hello('name'))
//2、通过 `hook(name,cb)` 创建插件
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('page:start', () => {
//业务逻辑存放处
})
nuxtApp.hook('vue:error', (..._args) => {
console.log('vue:error')
//
如果是客户端
if (process.client) {
console.log(..._args)
}
})
})
//3、callhook(name,...args)使用任何现有钩子调用时返回结果
await nuxtApp.callHook('my-plugin:init')
//useNuxtApp包含一下属性和方法
/****
*
* 1、component()
* 2、directive()
* 3、use()
* 4、ssrContext:url,event,payload
* 5、payload
* 6、isHydrating
*
****/
</script>
13、useRequestHeaders来访问传入的请求标头。例如:
// 获取所有请求头
const headers = useRequestHeaders()
// 仅获取请求头 cookie
const headers = useRequestHeaders(['cookie'])
14、 useRouter获取路由器实例。例如:
const router = useRouter();
router.back();
router.forward();
router.go();
router.push({ path: "/home" });
router.replace({ hash: "#bio" });
15、useRuntimeConfig公共配置变量。使用如下:
//客户端
<script setup lang="ts">
const config = useRuntimeConfig()
</script>
//服务端
export default defineEventHandler((event) => {
const config = useRuntimeConfig()
})
//定义运行时配置
export default defineNuxtConfig({
runtimeConfig: {
// 端口
apiSecret: '123',
// 公共请求地址
public: {
apiBase: process.env.NUXT_PUBLIC_API_BASE || '/api'
}
}
})
16、useState。详细如下:
/* _oo0oo_
* o8888888o
* 88" . "88
* (| -_- |)
* 0\ = /0
* ___/`---'\___
* .' \\| |// '.
* / \\||| : |||// \
* / _||||| -:- |||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' |_/ |
* \ .-\__ '-' ___/-. /
* ___'. .' /--.--\ `. .'___
* ."" '< `.___\_<|>_/___.' >' "".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `_. \_ __\ /__ _/ .-` / /
* =====`-.____`.___ \_____/___.-`___.-'=====
* `=---='
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 佛祖保佑 永不宕机 永无BUG
* @Description: 组合API
* @version:1.2.0
* @Date: 2022-09-14 16:24:57
* @Author: wenBin
*/
// key:确保数据获取在请求之间正确重复数据删除的唯一键
// init:一个在未启动时为状态提供初始值的函数。这个函数也可以返回一个`Ref`
// T:指定状态的类型
useState<T>(init?: () => T | Ref<T>): Ref<T>
useState<T>(key: string, init?: () => T | Ref<T>): Ref<T>
总结:以上就是Nuxt3中常用的组合API,有极个别API在开发中很少使用,因此,我们只需要详细了解我们开发中常用的那些即可。