6、Nuxt3实战请求、数据获取——详解及useState和useCookie的使用

2,980 阅读1分钟

一、与传统方式不同,Nuxt3内置了四种请求方式

1、useFetch

2、useLazyFetch

3、useAsyncData

4、useLazyAsyncData

注意:1、useFetch 和 useLazyFetch,useAsyncData和useLazyAsyncData 区别,服务端渲染的时候,这两个没差别,在客户端渲染的时候,useLazyFetch 相当于请求是数据是 suspense 的,而 useLazyFetch 一定要全部请求完毕,才进行路由内容的显示。2、我们更多使用的是useAsyncData和useFetch

异步获取数据:

例如:useAsyncData

    const {
    data:Ref<DataT>,//返回数据
    pending:Ref<boolean>, //请求数据指示器
    refresh:(force?:boolen) => promise<voild>, //强制刷新
    error?:any //错误信息
    } = useAsyncData(
        key:string, //唯一键,防止重复请求
        fn:() => Obiect, //返回数据一步函数
        options?:{lazy: boolean,server: boolean} //lazy是否路由加载后请求,server是否服务端请求
    )
    
//demo
<template>
    <h3>你好</h3>
</template>

<script setup lang="ts">
    const data. = {
        'userName':'17727272727',
        'pwd':'123456'
    }
    const { data:<dataT> }  = await. useAsyncData({
        'data',() => $fetch('Api地址')
    })

</script>

<style scoped>

</style>

例如:usefetch,它是对 useAsyncData的包装,可以自动生成 key,同时推断出响应类型;demo

const {
    data:Ref<DataT>,//返回数据
    pending:Ref<boolean>, //请求数据指示器
    refresh:(force?:boolen) => promise<voild>, //强制刷新
    error?:any //错误信息
} = useFetch(url:string, options?)

注意 :useLazyAsyncDatauseLazyFetch 只是设置了 lazy,如果lazy:true,不会阻塞路由导航。 返回的数据会存放在 payload中,如果我们只想要我们用到的字段,我们可以设置 $fetchpick ,例如 :

const {data:<dataT>} = await useFetch(
    'api',{pick:['userName','userImg','id']}
)

二、在Nuxt3中,创建api之前,首先需要在根目录下创建一个 ``server 目录,Nuxt3 会自动检索目录中的 api 目录,routes 目录以及middleware目录,并根据这些目录里面的文件名自动创建对应的api。例如:

三、为了方便我管理,来封装一个 useFetch 请求,新建utils/request.ts

import { _AsyncData } from 'nuxt3/dist/app/composables/asyncData'
//import baseUrl from './baseUrl'
import { ElMessage } from 'element-plus'

//接口地址配置
let baseUrl = ''
// 返回的基本数据类型
export interface ResponseConfig {
    code: number,
    status: number,
    data: any,
    msg: string
}
export interface ValueConfig {
    value: any

}

//fetch 请求

const fetch = (url: string, options?: any): Promise<any>  => {
    const reqUrl = baseUrl + url
    return new Promise((resolve, reject) => {
        useFetch(reqUrl, { ...options }).then(({ data, error }: _AsyncData) => {
            if (error.value) {
                reject(error.value)
                return
            }
            const value = data.value
            if (!value) {
                // 这里处理错误回调
                // reject(value)
                // $router.replace('/reject/' + value.status)
            }else if(value.code == 102){
                //用户未登录或登录过期
                ElMessage({
                    message: value.msg,
                    type: 'error',
                })
            } else {
                resolve(ref(value))
            }
        }).catch((err: any) => {
            reject(err)
        })
    })
}

export default new class Http {

    get(url: string, params?: any): Promise<any> {
        return fetch(url, { method: 'get', params })
    }

    post(url: string, params?: any): Promise<any>  {
        return fetch(url, { method: 'post', params })
    }

    put(url: string, body?: any): Promise<any>  {
        return fetch(url, { method: 'put', body })
    }

    delete(url: string, body?: any): Promise<any>  {
        return fetch(url, { method: 'delete', body })
    }
}

三、新建一个API管理文件,utils/api.ts

import Http from '@/utils/http'

export const config1 = (params?) => {
    return Http.get('接口地址', params)
}

export const config2 = (params?) => {
    return Http.post('接口地址', params)
}

四、在页面中使用,例如:

<template>
    <h3>你好</h3>
</template>

<script setup lang="ts">
 //按需引入
import { ref, reactive, onMounted, getCurrentInstance }  from 'vue'
 //引入 api中对应的接口请求
import {config1,config2} from "../utils/api"

interface ArrayList {
    banner: object
}
const state:ArrayList = reactive({
    banner:[],
})

//config1
config1('').then(res => {
  state.banner = res.value.data.listlunbos
}).catch((err)=>{
  console.log(err)
})

//config2
const data = {}
config2(data).then((res) => {
  if(res.value.code == 200){
    state.cooporationTost = false
    ElMessage({
      message: '我们会第一时间与您联系',
      type: 'success',
    })
  }else{
    ElMessage({
      message: res.value.data.message,
      type: 'success',
    })
  }
}).catch((err) => {
  console.log(err)
})

</script>

<style scoped>

</style>

五、useState和useCookie的使用

在Nuxt2中,如果我们要使用 cookie 。我们需要引入插件。js-cookie,在 Nuxt3 中,不再集成 Vuex,我们可以利用 Nuxt3composables自动导入属性,把它们定义在 composables目录中,这样他们将成为全局类型安全状态。

1、useState的使用

首先我们需要在项目的根目录创建 composables文件夹,然后创建状态管理文件。例如:

//首先引入useState、useCookie
import { useState, useCookie } from "nuxt/app";

export const useInfo = () => useState("userData",() => {
    return {
        id: 1,
        name: '用户1'
    }
})

// token
export const useToken = () => useState("token",()=> "aaadd232cfdfdf23fdf") 

如何修改 state 的值

<template>
    <h3>你好</h3>
</template>

<script setup lang="ts">
  
	const userData = useInfo();

	const token = useToken();

</script>

<style scoped>

</style>

1、useCookie的使用

<template>
    <h3>你好</h3>
</template>

<script setup lang="ts">
  
    // 获取 Cookie
    const Cookies = useCookie('token')

    // 设置 Cookie
    Cookies.value = Cookies.value || ''

    // 删除  Cookie
    Cookie.value = undefined || null

</script>

<style scoped>

</style>