Nuxt3 - useState全局状态管理与localStorage本地存储持久化

目录

一、useState - Nuxt3中的全局状态管理

1. 介绍

2. 基本使用

· 创建文件

· 创建需要全局共享的变量并导出

 · 使用(展示)

 · 使用(修改)

二、持久化

三、总结


一、useState - Nuxt3中的全局状态管理

1. 介绍

这是Nuxt3为我们准备的全局状态管理,且支持响应式,可以无需使用pinia等,直接在项目中使用。

官网文档useState · Nuxt Composables 、 State Management · Get Started with Nuxt

注意事项

· 由于会把State存储为JSON,所以请不要存储不能被JSON化的数据,比如类、函数、Symbol等

· 为了让我们的状态管理能在任何地方使用(不止在setup中),最好统一使用函数的写法,见下

2. 基本使用

· 创建文件

在根目录下的 /composables 文件夹中新建文件state.ts  (没有这个文件夹就新建,为什么放在这个文件夹,是因为这个文件夹里导出的函数,Nuxt会帮我们自动引入,官网文档: composables/ · Nuxt Directory Structure

· 创建需要全局共享的变量并导出

统一一下命名:导出的函数的格式为 useXxx

讲解一下 useState 函数的用法

第一个参数是全局唯一的键值(就比如你这个变量想叫什么名字),如下方代码中的 'color'和‘people’(千万不要出现重复的键值)

第二个参数是该状态的值,用函数形式表达,比如下方的 ()=>'red',实际的值就是 'red' 。

然后整个useState 作为一个箭头函数的返回值,赋值给 useXxx  (为了能在任意地方都能使用state)

// state.ts

/**简单数据类型示例 */
export const useColor = () => useState<string>('color', () => 'red')


/**复杂数据类型示例 */
interface test{
    /**姓名 */
    name: string,
    /**年龄 */
    age: number
    /**数组 */
    arr: number[]
}
export const usePeople = () =>  useState<test>('people',()=>({ //箭头函数return对象时的简写
    name: '小明',
    age: 18,
    arr: [1,2]
}))

 · 使用(展示)

在任意想使用全局状态的文件中(不止.vue文件),输入  const color = useColor()

在JS / TS代码中, color.value即可获取color真正的值 (和vue3中的ref数据使用方法一模一样)

在template模板中,直接 { { color }} 即可,无需 .value (和vue3中的ref数据使用方法一模一样)

<template>
    <div>{
   
   { color }} </div>
    <div>{
   
   { people.name}} </div>
</template>

<script setup lang='ts'>
//直接使用下面这俩函数,无需导入,因为Nuxt帮我们导入了
const color = useColor() 
const people = usePeople()

//在js代码中使用
const func = ()=>{
    if(color.value === 'red'){
        console.log('是红色')
    }
}

</script>

 · 使用(修改)

在任意地方都能修改(不止.vue文件)。示例见下: (和vue3中的ref数据使用方法一模一样

下面的修改方法都能触发页面的响应式

//直接使用下面这俩函数,无需导入,因为Nuxt帮我们导入了
const color = useColor() 
const people = usePeople()

//在js代码中修改
color.value = 'black' //简单数据类型直接.value修改
people.value.name = '小黑'  //复杂数据类型可以像这样一个个属性修改
people.value = { //也可以像这样直接赋值新对象,反正都能响应式
  name: '小黑',
  age: 10,
  arr: [1,2,3,4]
}

二、持久化(按需)

        上面的数据只是存储在内存中的,当浏览器刷新或者关闭后,重新打开就恢复原样了。很多时候我们需要对数据进行持久化(保存在localStorage中)

        注意:由于Nuxt是服务端渲染,localStorage只能在挂载后才能使用!!

        下面是我自己写的一种实现持久化的方法,大家也可以自己发挥。只要知道在onMounted后使用就行。

        因为不是所有数据都需要持久化,所以我做了一些适配:

        只有需要的数据才会持久化,根据函数名自动存储为对应的键放在localStorage中。(比如useColor会变为color存储在localStorage中,usePeople会变为people。但是多驼峰的也会全变为小写,比如useAaaBbb,会变为aaabbb存储,你可以根据需要修改,反正不影响代码运行)

        持久化时机:在app挂载时,从localStorage获取数据赋值到State中,在页面将要关闭/刷新时,把State数据放到localStorage中。 

// state.ts

/**简单数据类型示例 */
export const useColor = () => useState<string>('color', () => 'red')
/**复杂数据类型示例 */
interface test{
    /**姓名 */
    name: string,
    /**年龄 */
    age: number
    /**数组 */
    arr: number[]
}
export const usePeople = () =>  useState<test>('people',()=>({
    name: '小明',
    age: 18,
    arr: [1,2]
}))
/** 不需要持久化的数据示例 */
export const useXxx = () => useState<string>('Xxx', () => '我不需要持久化')

// 下面是持久化相关的代码


/**需要进行持久化的数据:把需要持久化的数据放在下面这个对象中,才会持久化,不需要持久化的数据就不用放到这里了。 */
const enduring: { [key: string]: () => Ref<any> } = {
    useColor, usePeople
}
//下面的俩函数在app.vue的onMounted中统一调用,或者在其它情况挂载后单独调用。
/**把所有指定数据保存到本地存储 
 * @param key 要保存的数据名。不填的话就是保存全部(一般不填,统一在页面关闭时保存。如果是特别重要的数据,就时不时单独保存一下即可。)
 */
export const setLocal = (key?: string) => {
    if (key) {
        console.log('只保存', key);
        const useKey = 'use' + key.slice(0, 1).toUpperCase() + key.slice(1).toLowerCase();//首字母大写,其它全部转小写
        const func = enduring[useKey]
        if (!func) {
            console.log('没有找到', useKey, '对应的函数');
            return
        }
        localStorage.setItem(key, JSON.stringify(func().value))
    } else {
        console.log('正在保存全部数据');
        for (const key in enduring) {
            if (Object.prototype.hasOwnProperty.call(enduring, key)) {
                const element = enduring[key];
                const setKey = key.toLowerCase().substring(3)//去掉前面的use ,其它全部转小写
                try {
                    localStorage.setItem(setKey, JSON.stringify(element().value))
                } catch (error) {
                    console.log(`在设置${setKey}的数据时出现错误`, error);
                }
            }
        }
    }
}
/**从本地存储获取数据到state中 */
export const getLoacl = () => {
    for (const key in enduring) {
        if (Object.prototype.hasOwnProperty.call(enduring, key)) {
            const element = enduring[key];
            const setKey = key.toLowerCase().substring(3)//去掉前面的use ,其它全部转小写
            try {
                const localData = localStorage.getItem(setKey) || ''
                if (localData) {
                    element().value = JSON.parse(localData)
                    console.log(setKey, '的本地存储数据获取成功', element().value);
                }
            } catch (error) {
                console.log(`在获取${setKey}的数据时出现错误`, error);
            }
        }
    }
}

然后在app.vue中,进行下面的操作:   下面的俩函数无需引入,Nuxt自动帮我们引入了

<template>
  <div class="App">
     <!-- 这里是APP.vue !!!!! --> 
     <NuxtPage />
  </div>
</template>
<script setup lang="ts"> 
//挂载钩子
onMounted(() => {//必须在onMounted的时候才能用local和window  
  getLoacl()
  window.onbeforeunload = () => {//离开页面时保存数据,由于可能突发情况,所以重要数据请手动调用setLocal函数
    setLocal() //如果需要调试本地存储数据,记得把这个注释一下
  }
})
</script>

        以上就实现了按需持久化数据。注:window.onbeforeunload 是会在页面关闭或刷新时执行,但是意外关闭的浏览器不会执行这个函数,所以重要的数据记得时不时单独调用一下 setLocal('xxx') 函数,保证数据持久化(可以利用watch监听,或者简单粗暴的定时器)

三、总结

        关于Nuxt3的全局状态与持久化就讲到这里了,以上代码是我个人思考的产物,可能有的地方不合理,请多多指教。()

猜你喜欢

转载自blog.csdn.net/m0_64130892/article/details/131714475