【问题标题】:Nuxt3 + Pinia + VueUse -> useStorage() not workingNuxt3 + Pinia + VueUse -> useStorage() 不工作
【发布时间】:2022-10-05 15:53:35
【问题描述】:

设置:我正在使用 Nuxt3 + Pinia + VueUse。

目标:我想通过 VueUse 将 pinia 商店的状态保存到本地存储:useStorage

问题:由于某种原因,本地存储中没有创建任何项目。我觉得我在这里错过了一些东西。在组件中我可以使用useStorage 很好。

商店/piniaStoreVueUse.js

import { defineStore } from \'pinia\'
import { useStorage } from \'@vueuse/core\'

export const usePiniaStoreVueUse = defineStore(\'piniaStoreUseVue\', {
    state: () => {
        return { 
            state: useStorage(\'my-state\', \'empty\'),
        }
    },
    actions: {
        enrollState() {
            this.state = \'enroll\';
        },
        emptyState() {
            this.state = \'empty\'; 
        },
    },
    getters: {
    }
});

组件/SampleComponentStatePiniaVueUse.vue

<script lang=\"ts\" setup>
    import { usePiniaStoreVueUse } from \'~/stores/piniaStoreVueUse\';

    const piniaStoreVueUse = usePiniaStoreVueUse();
</script>

<template>
    <div>
        piniaStoreVueUse.state: {{ piniaStoreVueUse.state }}<br>
        <button class=\"button\" @click=\"piniaStoreVueUse.enrollState()\">
            enrollState
        </button>
        <button class=\"button\" @click=\"piniaStoreVueUse.emptyState()\">
            clearState
        </button>
    </div>
</template>

<style scoped>
</style>

Live Version here

谢谢你。

  • 我的本地存储中确实有一个成功的piniaStoreState: \"empty\"。这不正是这里所期望的吗?还是我错过了什么?
  • 啊,我刚刚找到了一个修复程序并将其上线。我会在一分钟内将其添加为答案

标签: vuejs2 nuxt.js nuxtjs3 pinia vueuse


【解决方案1】:

我找到了一个答案:

Nuxt3 默认使用 SSR。但是由于 useStorage()(来自 VueUse)使用浏览器的 localstorage,所以这是行不通的。

解决方案1:

在您的nuxt.config.js 中禁用 SSR

export default defineNuxtConfig({
  ssr: false,
  
  // ... other options
})

小心:
这将全局禁用 SSR。

解决方案2:

将您的组件包装在 <client-only placeholder="Loading...">

 <client-only placeholder="Loading...">
    <MyComponent class="component-block"/>
 </client-only>

我很想听听其他方法来处理这个问题。我觉得应该有更好的方法。

【讨论】:

  • 您还可以像if (process.client) { 那样进行快速检查,以仅应用特定方法在前端运行。否则,一些生命周期钩子也是called only on the client-side
【解决方案2】:

我关注了这个话题两周。我已解决使用插件pinia-plugin-persistedstate. 我触摸 plugin/persistedstate.js 并添加persist: true,在 Pinia defineStore()

首先安装插件yarn add pinia-plugin-persistedstatenpm i pinia-plugin-persistedstate

#plugin/persistedstate.js
import { createNuxtPersistedState } from 'pinia-plugin-persistedstate'

export default defineNuxtPlugin(nuxtApp => {
 nuxtApp.$pinia.use(createNuxtPersistedState(useCookie))
})

#story.js
export const useMainStore = defineStore('mainStore', {
state: () => {
    return {
        todos: useStorage('todos', []),
        ...
    }
},
persist: true, #add this
getters: {...},
actions: {...}
})

【讨论】:

【解决方案3】:

我找到了解决这个问题的方法,它似乎工作得很好。我没有进行广泛的测试,但它似乎有效。

经过大量挖掘后,我在 Pinia 文档中看到了一个页面:Dealing with Composables

我的测试代码:

//storageTestStore.js

import { defineStore, skipHydrate } from "pinia";
import { useLocalStorage } from '@vueuse/core'

export const useStorageTestStore = defineStore('storageTest', {
    state: () => ({
      user: useLocalStorage('pinia/auth/login', 'bob'),
    }),
    actions: {
        setUser(user) {
            this.user = user
        }
    },
  
    hydrate(state, initialState) {
      // in this case we can completely ignore the initial state since we
      // want to read the value from the browser
      state.user = useLocalStorage('pinia/auth/login', 'bob')
    },
  })
// test.vue (~~/pages/test.vue)

<script setup>
    import { ref, onMounted } from "vue";
    import { useStorageTestStore } from "~~/stores/storageTestStore";

    const storageTestStore = useStorageTestStore();

    // create array with 10 random first names
    const firstNames = [
        "James",
        "John",
        "Robert",
        "Michael",
        "William",
        "David",
        "Richard",
        "Charles",
        "Joseph",
        "Thomas",
    ];

    const updateUser = () => {
        storageTestStore.setUser(
            firstNames[Math.floor(Math.random() * firstNames.length)]
        );
    };
</script>

<template>
    <div class="max-w-[1152px] mx-auto">
        <h1 class="text-xl">{{ storageTestStore.user }}</h1>
        <button
            class="text-lg bg-emerald-300 text-emerald-900 p-5 rounded-lg"
            @click="updateUser()"
        >
            Change User
        </button>
    </div>
</template>

<style scoped></style>

【讨论】:

    【解决方案4】:

    您可以将 ref 与 useStorage() 一起使用

    import { defineStore } from 'pinia'
    import { useStorage } from '@vueuse/core'
    
    export const usePiniaStoreVueUse = defineStore('piniaStoreUseVue', {
        state: () => {
            return { 
                state: ref(useStorage('my-state', 'empty')),
            }
        },
        actions: {
            enrollState() {
                this.state = 'enroll';
            },
            emptyState() {
                this.state = 'empty'; 
            },
        },
        getters: {
        }
    });
    

    【讨论】:

    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
    • 出于某种原因,这不会创建 localStorage 项目,但它确实有效并且状态是持久的。谢谢你。
    猜你喜欢
    • 2022-12-04
    • 2022-10-18
    • 2022-08-17
    • 2023-02-07
    • 2022-07-06
    • 2022-01-24
    • 2017-05-11
    • 2022-08-16
    • 2022-06-15
    相关资源
    最近更新 更多