iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >怎么在Vue中使localStorage具有响应式
  • 289
分享到

怎么在Vue中使localStorage具有响应式

2024-04-02 19:04:59 289人浏览 薄情痞子
摘要

这篇文章主要介绍“怎么在Vue中使localStorage具有响应式”,在日常操作中,相信很多人在怎么在Vue中使localStorage具有响应式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方

这篇文章主要介绍“怎么在Vue中使localStorage具有响应式”,在日常操作中,相信很多人在怎么在Vue中使localStorage具有响应式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么在Vue中使localStorage具有响应式”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

响应式是vue.js的最大特色之一。如果你不知道幕后情况,它也是最神秘的地方之一。例如,为什么它不能用于对象和数组,而不能用于诸如  localStorage 之类的其他东西?

怎么在Vue中使localStorage具有响应式

让我们回答这个问题,在解决这个问题时,让Vue响应式与 localStorage 一起使用。

如果运行以下代码,则会看到计数器显示为静态值,并且不会像我们期望的那样发生变化,这是因为setInterval在 localStorage  中更改了该值。

new Vue({   el: "#counter",   data: () => ({     counter: localStorage.getItem("counter")   }),   computed: {     even() {       return this.counter % 2 == 0;     }   },   template: `<div>     <div>Counter: {{ counter }}</div>     <div>Counter is {{ even ? 'even' : 'odd' }}</div>   </div>` });
// some-other-file.js setInterval(() => {   const counter = localStorage.getItem("counter");   localStorage.setItem("counter", +counter + 1); }, 1000);

尽管Vue.js实例中的 counter 属性是响应式的,但它不会因为我们更改了它在 localStorage 中的来源而更改。

有多种解决方案,最好的也许是使用Vuex,并保持存储值与 localStorage  同步。但如果我们需要像本例中那样简单的东西呢?我们要深入了解一下Vue.js的响应式系统是如何工作的。

Vue 中的响应式

当Vue初始化组件实例时,它将观察data选项。这意味着它将遍历数据中的所有属性,并使用 Object.defineProperty  将它们转换为getter/setter。通过为每个属性设置自定义设置器,Vue可以知道属性何时发生更改,并且可以通知需要对更改做出反应的依赖者。它如何知道哪些依赖者依赖于一个属性?通过接入getters,它可以在计算的属性、观察者函数或渲染函数访问数据属性时进行注册。

// core/instance/state.js function initData () {   // ...   observe(data) }
// core/observer/index.js export function observe (value) {   // ...   new Observer(value)   // ... }  export class Observer {   // ...   constructor (value) {     // ...     this.walk(value)   }      walk (obj) {     const keys = Object.keys(obj)     for (let i = 0; i < keys.length; i++) {       defineReactive(obj, keys[i])     }   } }   export function defineReactive (obj, key, ...) {   const dep = new Dep()   // ...   Object.defineProperty(obj, key, {     // ...     get() {       // ...       dep.depend()       // ...     },     set(newVal) {       // ...       dep.notify()     }   }) }

所以,为什么 localStorage 不响应?因为它不是具有属性的对象。

但是等一下,我们也不能用数组定义getter和setter,但Vue中的数组仍然是反应式的。这是因为数组在Vue中是一种特殊情况。为了拥有响应式的数组,Vue在后台重写了数组方法,并与Vue的响应式系统进行了修补。

我们可以对 localStorage 做类似的事情吗?

覆盖localStorage函数

首先尝试通过覆盖localStorage方法来修复最初的示例,以跟踪哪些组件实例请求了localStorage项目

// LocalStorage项目键与依赖它的Vue实例列表之间的映射。 const storeItemSubscribers = {};  const getItem = window.localStorage.getItem; localStorage.getItem = (key, target) => {   console.info("Getting", key);    // 收集依赖的Vue实例   if (!storeItemSubscribers[key]) storeItemSubscribers[key] = [];   if (target) storeItemSubscribers[key].push(target);    // 调用原始函数    return getItem.call(localStorage, key); };  const setItem = window.localStorage.setItem; localStorage.setItem = (key, value) => {   console.info("Setting", key, value);    // 更新相关Vue实例中的值   if (storeItemSubscribers[key]) {     storeItemSubscribers[key].forEach((dep) => {       if (dep.hasOwnProperty(key)) dep[key] = value;     });   }    // 调用原始函数    setItem.call(localStorage, key, value); };
new Vue({   el: "#counter",   data: function() {     return {       counter: localStorage.getItem("counter", this) // 我们现在需要传递“this”     }   },   computed: {     even() {       return this.counter % 2 == 0;     }   },   template: `<div>     <div>Counter: {{ counter }}</div>     <div>Counter is {{ even ? 'even' : 'odd' }}</div>   </div>` });
setInterval(() => {   const counter = localStorage.getItem("counter");   localStorage.setItem("counter", +counter + 1); }, 1000);

在这个例子中,我们重新定义了 getItem 和 setItem,以便收集和通知依赖 localStorage 项目的组件。在新的 getItem  中,我们注意到哪个组件请求了哪个项目,在 setItems 中,我们联系所有请求该项目的组件,并重写它们的数据属性。

为了使上面的代码工作,我们必须向 getItem 传递一个对组件实例的引用,这就改变了它的函数签名。我们也不能再使用箭头函数了,因为否则我们就不会有正确的  this 值。

如果我们想做得更好,就必须更深入地挖掘。例如,我们如何在不显式传递依赖者的情况下跟踪它们?

怎么在Vue中使localStorage具有响应式

Vue如何收集依赖关系

为了获得启发,我们可以回到Vue的响应式系统。我们之前曾看到,访问数据属性时,数据属性的 getter  将使调用者订阅该属性的进一步更改。但是它怎么知道是谁做的调用呢?当我们得到一个数据属性时,它的 getter  函数没有任何关于调用者是谁的输入。Getter函数没有输入,它怎么知道谁要注册为依赖者呢?

每个数据属性维护一个需要在Dep类中进行响应的依赖项列表。如果我们在此类中进行更深入的研究,可以看到只要在注册依赖项时就已经在静态目标变量中定义了依赖项。这个目标是由一个非常神秘的Watche类确定的。实际上,当数据属性更改时,将实际通知这些观察程序,并且它们将启动组件的重新渲染或计算属性的重新计算。

但是,他们又是谁?

当Vue使 data  选项可观察时,它还会为每个计算出的属性函数以及所有watch函数(不应与Watcher类混为一谈)以及每个组件实例的render函数创建watcher。观察者就像这些函数的伴侣。他们主要做两件事:

  • 当它们被创建时,它们会评估函数。这将触发依赖关系的集合

  • 当他们被通知他们所依赖的一个值发生变化时,他们会重新运行他们的函数。这将最终重新计算一个计算出的属性或重新渲染整个组件。

在观察者调用其负责的函数之前,有一个重要的步骤发生了:他们将自己设置为Dep类中静态变量的目标。这样可以确保在访问响应式数据属性时将它们注册为从属。

追踪谁调用了localStorage

我们无法完全做到这一点,因为我们无法使用Vue的内部机制。但是,我们可以使用Vue的想法,即观察者可以在调用其负责的函数之前,将目标设置为静态属性。我们能否在调用  localStorage 之前设置对组件实例的引用?

如果我们假设在设置 data 选项时调用了 localStorage,则可以将其插入 beforeCreate 和 created  中。这两个挂钩在初始化data选项之前和之后都会被触发,因此我们可以设置一个目标变量,然后清除该变量,并引用当前组件实例(我们可以在生命周期挂钩中访问该实例)。然后,在我们的自定义获取器中,我们可以将该目标注册为依赖项。

我们要做的最后一点是使这些生命周期挂钩成为我们所有组件的一部分,我们可以通过整个项目的全局混合来做到这一点。

// LocalStorage项目键与依赖它的Vue实例列表之间的映射 const storeItemSubscribers = {};  // 当前正在初始化的Vue实例 let target = undefined;  const getItem = window.localStorage.getItem; localStorage.getItem = (key) => {   console.info("Getting", key);    // 收集依赖的Vue实例   if (!storeItemSubscribers[key]) storeItemSubscribers[key] = [];   if (target) storeItemSubscribers[key].push(target);    // 调用原始函数    return getItem.call(localStorage, key); };  const setItem = window.localStorage.setItem; localStorage.setItem = (key, value) => {   console.info("Setting", key, value);    // 更新相关Vue实例中的值   if (storeItemSubscribers[key]) {     storeItemSubscribers[key].forEach((dep) => {       if (dep.hasOwnProperty(key)) dep[key] = value;     });   }      // 调用原始函数    setItem.call(localStorage, key, value); };  Vue.mixin({   beforeCreate() {     console.log("beforeCreate", this._uid);     target = this;   },   created() {     console.log("created", this._uid);     target = undefined;   } });

现在,当我们运行第一个示例时,我们将获得一个计数器,该计数器每秒增加一个数字。

new Vue({   el: "#counter",   data: () => ({     counter: localStorage.getItem("counter")   }),   computed: {     even() {       return this.counter % 2 == 0;     }   },   template: `<div class="component">     <div>Counter: {{ counter }}</div>     <div>Counter is {{ even ? 'even' : 'odd' }}</div>   </div>` });
setInterval(() => {   const counter = localStorage.getItem("counter");   localStorage.setItem("counter", +counter + 1); }, 1000);

到此,关于“怎么在Vue中使localStorage具有响应式”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 怎么在Vue中使localStorage具有响应式

本文链接: https://www.lsjlt.com/news/84886.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在Vue中使localStorage具有响应式
    这篇文章主要介绍“怎么在Vue中使localStorage具有响应式”,在日常操作中,相信很多人在怎么在Vue中使localStorage具有响应式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方...
    99+
    2022-10-19
  • 如何使在Vue之外创建的变量具有响应性
    这篇文章给大家分享的是有关如何使在Vue之外创建的变量具有响应性的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。如果你从 Vue 外部获得一个变量,那么能够使其具有响应性就很好。这样你就可以在计...
    99+
    2023-06-27
  • 怎么在css中实现响应式布局
    今天就跟大家聊聊有关怎么在css中实现响应式布局,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。响应式布局的四种方式总的html代码<body>  &n...
    99+
    2023-06-15
  • vue中怎么使用localStorage实现在界面刷新时清除数据
    本篇文章为大家展示了vue中怎么使用localStorage实现在界面刷新时清除数据,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。vue中使用方法:1、新建一个st...
    99+
    2022-10-19
  • vue中provide inject的响应式监听问题怎么解决
    这篇文章主要介绍“vue中provide inject的响应式监听问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vue中provide inject的响应式监听问题怎...
    99+
    2023-06-30
  • 怎么使用Vue-TCB快速在Vue应用中接入云开发
    这篇文章主要介绍怎么使用Vue-TCB快速在Vue应用中接入云开发,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!什么是 Vue TCB我自己平时经常会用到 Vue 来开发前端应用。所...
    99+
    2022-10-19
  • css3中怎么使用@media属性实现页面响应式布局
    这篇文章将为大家详细讲解有关css3中怎么使用@media属性实现页面响应式布局,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。<!DOCTYPE HT...
    99+
    2022-10-19
  • 你知道怎么在Java中使用二维码响应框架吗?
    在当今数字化的时代,二维码已经成为了一种常见的信息传递方式。在Java中,我们可以使用一些二维码响应框架来创建和解析二维码。在本文中,我们将介绍如何在Java中使用二维码响应框架,以及如何创建和解析二维码。 二维码响应框架是一个用于创建和解...
    99+
    2023-06-13
    二维码 响应 框架
  • vue怎么通过props方式在子组件中获取相应的对象
    本文小编为大家详细介绍“vue怎么通过props方式在子组件中获取相应的对象”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue怎么通过props方式在子组件中获取相应的对象”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习...
    99+
    2023-06-30
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作