有啥方法可以让 Vue3 中的 sessionStorage 响应式?

Posted

技术标签:

【中文标题】有啥方法可以让 Vue3 中的 sessionStorage 响应式?【英文标题】:Any way to make sessionStorage reactive in Vue3?有什么方法可以让 Vue3 中的 sessionStorage 响应式? 【发布时间】:2021-12-15 17:29:54 【问题描述】:

假设我构建了一个应用程序,它每次加载或刷新时都会通过 axios.get 从数据库中获取数据。这让app变慢了,所以我只想把app的initial load里面的数据拿到sessionStorage里面。

问题是sessionStorage 没有反应。当我这样做时:

const state = reactive(
    image: sessionStorage.image
)

并且想要渲染:

  <div class="home-image" :style="'background-image': 'url(' + state.image + ')'"></div>

只有在sessionStorage 已在上一页加载中更新时才有效。对于初始页面加载,state.image 会抛出 404 not found

有没有办法让sessionStorage 反应?我读过关于watcherssetget 的文章,但不太明白。

解决方案(新):

Aaaa 实际上,我刚刚找到了一种方法,可以让 sessionStorageinitial load 期间表现得就像是 reactive,而我什至不需要 vuex

<script setup>
import reactive from 'vue';

const state = reactive(
    image: sessionStorage.image || ""
)

axios.get('/home')
    .then(res => 
        const data = res.data[0]
        state.image = sessionStorage.image = 'storage/' + data['image']
    )
</script>

这样reactive 函数会选择一个空字符串,如果sessionStorage 在初始加载期间未定义并将值从axios.get 分配给sessionStorage。在所有连续的页面加载中,reactive 函数使用 sessionStorage,它现在已经分配了一个值。

编码很有趣。有时您会学习如何用 1 个 LOC 替换 100 行代码。

解决方案(旧):

好的,现在我的存储按我想要的方式工作。它是globalreactivepersistent,易于使用。我会接受@Elsa 的回答,因为她帮我调查了vuex

我在单独的 store.js 文件中创建了一个store

import createStore from "vuex";

const store = createStore(
    state() 
        return 
            image: sessionStorage.image || ""
        
    
)
export default store

然后在app.js注册:

require('./bootstrap');

import createApp from 'vue';
import app from "../vue/app";
import store from "./store";

createApp(app)
    .use(store)
    .mount("#app");

现在我可以在我的组件中使用store,如下所示:

<template>
  <section id="home" class="home">
    <div class="image-container">
      <div class="home-image" :style="'background-image': 'url(' + store.state.image + ')'"></div>
    </div>
  </section>
</template>


<script setup>
import useStore from "vuex";

const store = useStore()

if (!sessionStorage.image) 
    axios.get('/home')
        .then(res => 
            const data = res.data[0]
            store.state.image = sessionStorage.image = 'storage/' + data['image']
        )

</script>

axios 请求仅在 sessionStorage.image 未定义时运行,否则直接呈现其值。如果链接存在,则图像不会首先在模板中新加载,而是立即渲染。

我现在可以完全省略state = reactive,因为我可以在全局范围内使用store.state,甚至可以将其链接到ss/ls。我唯一需要维护的是里面的字段:

const store = createStore(
    state() 
        return 
            image: sessionStorage.image || ""
        
    
)

因为如果我不这样做,vue 会抛出 404 errors(但由于反应性,无论如何都会渲染元素)。

【问题讨论】:

不,您不能以这种方式使 sessionStorage 反应。但是,这确实是 Vuex! 的用例! 为什么不使用提供和注入? @huanfeng 我更喜欢使用global reactive storage 【参考方案1】:

首先,sessionStorage 不能是响应式的。

如果我的理解正确,您只希望全局变量具有反应性。你可以简单地通过提供和注入来实现它:

const yourGlobalVar = sessionStorage.getItem('image');
app.provide('yourImage', ref(yourGlobalVar))

用在哪里:

setup()
   ...
   const image = inject('yourImage');
   ...
   return image

【讨论】:

我的主要问题是我需要一个persistent variable,它也可以使用reactively。如果没有sessionStorage/localStorage,我不知道如何实现这一点。似乎有一种方法可以在composition api 中创建global variables 并传递它们,但似乎没有办法让它们成为persistent 您可以添加一个层来提供一个get/set,每次从存储中获取数据并更改全局变量的值之后,以及在将数据设置到存储之前,更新全局变量。跨度> 【参考方案2】:

我一周前遇到了这个问题,我尝试了 3 种方法在 vue3 中使 sessionStorage 响应式。 1.vuex 2.创建事件监听器 3.设置间隔

我找到了解决 setInterval 问题的临时解决方案。

1.vuex

const state = () => 
  return 
    latInfo: sessionStorage.getItem('lat') || 0
  


const getters = 
  latInfo: state => state.latInfo

3.setInterval

  setup() 
    setInterval(() => 
      if (infoData) 
        infoData.lat = sessionStorage.getItem('lat')
      
    , 1000)

【讨论】:

欢迎您。是的,我看了你的解决方案。这个问题有几种解决方案。老实说,我必须为我的项目使用 setInterval,因为我需要将脚本部分反应到 html 页面中。我很高兴能够帮助您解决我的问题。

以上是关于有啥方法可以让 Vue3 中的 sessionStorage 响应式?的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以让浏览器页面避免 Pyqt5 中的重定向?

有啥方法可以让多个设备(人)在数据块中同时在不同的分支中工作?

Xcode:有啥方法可以刷新/重新运行游乐场?

vue3中的四种插槽的介绍-保证让你看看的明明白白!

有啥方法可以让 PHP 检测到损坏的图像?

有啥方法可以让文本阴影不显示在文本后面?