Skip to content

常用组合式函数

useCookie#

Cookie 的工作原理。

  1. 浏览器向服务器发送请求
  2. 服务器进行响应,并且在响应头里面通过 Set-Cookie 来指示浏览器保存或者更新 Cookie
  3. 浏览器保存最新的 Cookie
  4. 后续请求带上这个 Cookie

以前前端开发中要操作 Cookie 通过 document.cookie 接口进行操作。

读取Cookie

document.cookie 返回的是一个字符串,包含当前页面所有的 Cookie,每个 Cookie 之间用分号和空格分隔。你需要对这个字符串自行分割和解析

'name=value; expires=DATE; path=PATH; domain=DOMAIN; sameSite=VALUE'

更新 Cookie

通过重新赋值新的字符串给 document.cookie 可以设置新的 Cookie 值。

删除 Cookie

删除 Cookie 通常是将 Cookie 的过期时间设置为一个过去的时间。

思考一下🤔 SSR 场景下操作 Cookie 会遇到什么问题?

在 SSR 环境下,并没有浏览器的 DOM 对象,因此也就不存在 document.cookie。Nuxt 为我们提供了 useCookie 的组合式函数来做 Cookie 的处理。

useCookie 的基本用法:

读取 Cookie

const token = useCookie('token')
token.value

更新 Cookie

const token = useCookie('token')
token.value = 'new_token'

删除 Cookie

const token = useCookie('token')
token.value = null

useCookie 函数接受第二个参数 options,用于配置 Cookie 的行为。常见的配置选项包括:

例如,我们可以这样设置一个 Cookie 用于存储用户信息:

<script setup lang="ts">
const userInfo = useCookie('userInfo', {
maxAge: 60 * 60 * 24 * 30, // 30 天有效期
path: '/',
secure: true,
httpOnly: true,
sameSite: 'lax',
})
// 设置默认值或更新Cookie
userInfo.value = { username: 'Alice', score: 100 }
</script>

相较于原生的 document.cookie,有如下的优点:

惰性请求#

关于请求这一块儿,我们之前有接触过:

除此之外,Nuxt 还提供了惰性请求相关的组合式函数:

回忆 useAsyncData 的用法:

<script setup lang="ts">
const { data, status, error, refresh, clear } = await useAsyncData(
'mountains',
() => $fetch('https://api.nuxtjs.dev/mountains')
)
</script>

参数:

  1. key:为 useAsyncData 提供一个唯一标识符。Nuxt 根据提供的 key 检查是否已有缓存。如果缓存存在且有效,直接返回缓存数据。如果没有缓存或缓存失效,则调用 fetcher 函数获取数据。
  2. fetcher 函数:定义如何获取数据。

useAsyncData 还接收第三个参数。这个参数是一个配置对象,你可以在 官方文档 中看到该配置对象支持的所有配置项。其中有一个就是 lazy。如果 lazy 项设置为 true,这意味着导航不会等待数据获取完成,页面会立即渲染,数据获取在后台进行。

<template>
<div v-if="pending">加载中...</div>
<div v-else-if="error">加载失败:{{ error.message }}</div>
<div v-else>数据:{{ data }}</div>
</template>
<script setup>
const { data, pending, error } = await useAsyncData(
'unique-key',
() => new Promise((resolve) => setTimeout(() => resolve('模拟数据'), 5000)),
{
lazy: false,
// 默认其实就是 false
}
)
</script>

在初始 SSR 的时候,useAsyncData 会在服务器等待数据获取完成后再渲染页面。这样服务器生成的 html 是包含数据的,但是这也意味着服务器端在渲染首屏 html 的时候需要等待请求的时间。

useLoadingIndicator#

useLoadingIndicator 返回一个加载器实例对象,该对象提供 start() 和 finish() 等方法,用于在某个异步操作开始前启动加载效果,操作结束后结束加载效果。

<template>
<NuxtLoadingIndicator />
<div>
<button @click="fetchData">获取数据</button>
</div>
</template>
<script setup lang="ts">
const loading = useLoadingIndicator()
// 模拟一个异步数据请求
async function fetchData() {
// 开始加载
loading.start()
try {
// 模拟延时 3 秒后返回数据
const data = await new Promise((resolve) =>
setTimeout(() => resolve('模拟数据'), 3000)
)
console.log('获取到数据:', data)
} catch (error) {
console.error('数据获取失败:', error)
} finally {
// 数据请求完成后结束加载
loading.finish()
}
}
</script>

在这个例子中:

来看一个具体的例子。当用户点击“登录”按钮后,加载指示器开始工作,等待异步模拟的登录请求完成后再结束加载,从而让用户明确知道正在进行登录操作。

<template>
<NuxtLoadingIndicator />
<form @submit.prevent="handleSubmit">
<div>
<label for="username">用户名:</label>
<input
id="username"
v-model="username"
type="text"
placeholder="请输入用户名"
/>
</div>
<div>
<label for="password">密码:</label>
<input
id="password"
v-model="password"
type="password"
placeholder="请输入密码"
/>
</div>
<button type="submit">登录</button>
</form>
</template>
<script setup lang="ts">
const username = ref('')
const password = ref('')
// 获取加载指示器实例
const loading = useLoadingIndicator()
async function handleSubmit() {
// 启动加载效果
loading.start()
try {
// 模拟一个异步登录请求,延时 2 秒返回结果
const response = await new Promise((resolve) =>
setTimeout(() => resolve({ success: true }), 2000)
)
if (response.success) {
console.log('登录成功')
// 这里可以继续处理登录成功后的逻辑
} else {
console.error('登录失败')
}
} catch (error) {
console.error('请求出错:', error)
} finally {
// 无论成功或失败,都结束加载效果
loading.finish()
}
}
</script>

-EOF-