谈谈StorageEvent
纷纷红紫已成尘,布谷声中夏令新。夹路桑麻行不尽,始知身是太平人。 ——宋.陆游 《初夏绝句》
我们在开发多Tab应用时候,常常会遇到多个Tab状态同步的问题。
想象如下场景:用户主界面,显示用户购物车内待结算的商品总数。此时,用户可能打开多个Tab。当用户添加新商品到购物车的时候,需要更新购物车的数量。
此时,当前页面需要向服务器发起请求,在得到添加成功响应的时候,可以更新用户界面。为了兼顾体验和可靠性,如果确信添加成功概率比较高的时候,也可以先更新界面,当多数返回错误的时候,可以给用户界面做状态回滚。为了下次展示方便,我们还会把这个数据写到LocalStorage里面。用户再次打开时候,可以优先从localStorage中取值。
当前页面解决了,那么如果同时打开多个Tab该如何解决呢?这里使用StorageEvent可能是一种代价较小的解决方案。
StorageEvent是什么呢?
- 是一种Event,可以通过标准的Event监听器操作。
- 当storage变化时候,事件会被派发到所有同域下的其他页面。
- 触发变化的当前页面,没有事件派发。
这里有一个简单的示例可以展示这个API的用法。
const STORAGE_KEY = "cartlist"const getStorage = () => {try {let rets = window.localStorage.getItem(STORAGE_KEY)if (rets === null) {return []}return JSON.parse(rets)}catch(e){return []}
}const addCart = (value) => {let rets = getStorage()rets.push(value)window.localStorage.setItem(STORAGE_KEY, JSON.stringify(rets))return rets
}const minusCart = (value) => {let rets = getStorage()let idx = rets.indexOf(value)if (idx !== -1){rets.splice(idx, 1)window.localStorage.setItem(STORAGE_KEY, JSON.stringify(rets))}return rets
}const render = () => {let rets = getStorage()if (rets.length){$("#num").html(rets.length).show()}else {$("#num").hide()}$(".list li").each((i,el) => {if (rets.includes(i)){$(el).find("a:nth-child(1)").css("visibility", "hidden")$(el).find("a:nth-child(2)").css("visibility", "visible")}else {$(el).find("a:nth-child(1)").css("visibility", "visible")$(el).find("a:nth-child(2)").css("visibility", "hidden")}})
}$(".list a").on("click", (e)=> {let opIdx = $(e.target).parent().find("a").index(e.target)let line = $(e.target).parent().parent()let idx = $(".list li").index(line)opIdx === 0 ? addCart(idx) : minusCart(idx)render()return false
})window.addEventListener('storage', (e) => {render()
})render()
复制代码
其中,下面这行代码是实现的关键:
window.addEventListener('storage', (e) => {render()
})
复制代码
当我们注释掉这个语句,我们的页面同步就不能运行了。
读者可以打开多个Tab并观察页面的变化https://jsbin.com/radekilosu/1/edit?html,css,js,output。
实际上,这个事件e上还带有很多信息,方便编程时,对于事件做精确的控制。
字段 | 含义 |
---|---|
key | 发生变化的storageKey |
newValue | 变换后新值 |
oldValue | 变换前原值 |
storageArea | 相关的变化对象 |
url | 触发变化的URL,如果是frameset内,则是触发帧的URL |
上述各值都是只读的。
还有一点没有解决掉,就是触发storage变化的本页面,不能接收这个值,这个一般情况下是没问题。当然,为了一致性,我们可以自行new一个事件,在发生时候主动触发它。
此时我们可以包装一个新的Storage对象:
var Storage = {setItem : function(k,v){  localStorage.setItem(k,v);},removeItem : function(k){  localStorage.removeItem(k);},clear: function (){},getItem: function(k){}
}
复制代码
此时,我们再包装一个函数:
function dispatchMe(key, oldval, newval, url, storage){var se = document.createEvent("StorageEvent");se.initStorageEvent('storage', false, false, key, oldval, newval, url, storage);window.dispatchEvent(se);
}
复制代码
此时,我们只需要在setItem、removeItem、clear中获取对应的值,并手动调用一下dispatchMe,同时把和localStorage打交道的地方改为调用我们包装的Storage即可。
参考资料
- developer.mozilla.org/en-US/docs/…
- www.cnblogs.com/cczw/p/3196…
关于奇舞周刊
《奇舞周刊》是360公司专业前端团队「奇舞团」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。
转载于:https://juejin.im/post/5cee56dde51d45109725fe00
谈谈StorageEvent相关推荐
- 创建一个storageevent事件_谈谈StorageEvent
编者按:本文作者 刘观宇,360 奇舞团高级前端工程师.技术经理,W3C CSS 工作组成员. 纷纷红紫已成尘,布谷声中夏令新.夹路桑麻行不尽,始知身是太平人. --宋.陆游 <初夏绝句> ...
- 反arp攻击软件_谈谈电子欺骗中的ARP欺骗
ARP欺骗是一种非常古老的电子欺骗攻击,虽然从诞生到现在已经过去了二十多年,但在很多网络中仍然有效.之前写的 沈传宁:谈谈TCP/IP协议的学习zhuanlan.zhihu.com 文章中也提到,我 ...
- mysql注入实例获取答案_本文实例讲述了MySQL解决SQL注入的另类方法。分享给大家供大家参考,具体如下:问题解读我觉得,这个问题每年带来的成本可以高达数十亿美元了。本文就来谈谈,...
本文实例讲述了MySQL解决SQL注入的另类方法.分享给大家供大家参考,具体如下: 问题解读 我觉得,这个问题每年带来的成本可以高达数十亿美元了.本文就来谈谈,假定我们有如下 SQL 模板语句: se ...
- 谈谈C#中类成员的执行顺序.
今天我们来谈谈C#中子类和父类中静态成员以及构造函数的执行顺序,这个地方向来是初学C#的人比较迷惑的地方,也是各大公司最喜欢拿来出面试题的地方. 下面我们分情况来分析. 1. 普通构造函数和静态构造函 ...
- 谈谈UI架构设计的演化
谈谈UI架构设计的演化 经典MVC 在1979年,经典MVC模式被提出. 在当时,人们一直试图将纯粹描述思维中的对象与跟计算机环境打交道的代码隔离开来,而Trygve Reenskaug在跟一些人的讨 ...
- 谈谈Python那些不为人知的冷知识(二)
本文转载自Python的编程时光(ID:Python-Time) 小明在日常Code中遇到一些好玩,冷门的事情,通常都会记录下来. 从上一篇的分享来看,仍然有不少 Pythoner 对这些冷知识存在盲 ...
- 谈谈 Java 类加载机制
点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 来源:Rainstorm , github.com/c-rainstorm/blog/blob/m ...
- 13个Offer,8家SSP,谈谈我的秋招经验
前言 大家好,我是卖萌屋的小Q,是夕小瑶学姐的同实验室师弟(2020届).在学姐的建(bian)议(ce)下写了本文,希望能够给21届的师弟师妹提供一些启发,秋招之路能够更加顺利~ 往昔的回忆使我们激 ...
- 谈谈你对集成学习的见解与认识,描述一下它们的优势所在?
[每日一问]谈谈你对集成学习的见解与认识,描述一下它们的优势所在? Datawhale优秀回答者:HipHopMan 集成方法有很多种,一种叫做bagging,bagging的思想是,我把我的数据做一 ...
最新文章
- ROS系统 通过服务编程实现两个数相加并返回
- Cause: java.sql.SQLSyntaxErrorException: Expression #1 of SELECT list is not in GROUP BY错误
- python2.7获取当前脚本目录
- FFmpeg转OpenCV Mat显示
- AQS.transferForSignal
- XDP(eXpress Data Path)防御DDoS攻击
- python 加载mat文件
- enum 有什么好处_林卡尔|先买地板后装修的三大好处
- python字典求平均值_Python 3.4 – 如何获得字典值的平均值?
- MFC开发-垂直滚动条一直处于底部
- Python中的图书管理系统
- Uniswap 24h交易量约11亿美元涨10.66%
- Sublime Text 3安装、配置和快捷键
- BZOJ2337:[HNOI2011]XOR和路径——题解
- 【裂缝识别】基于matlab无人机图像处理公路裂缝检测研究与实现【含Matlab源码 1730期】
- yum快速安装mysql
- android 系统时间不准确,小米手机时间不准确怎么调小米手机时间不准确怎样调...
- VR中的9轴传感器(重力加速度/陀螺仪/磁力计).md
- 云南怎么办理ICP经营许可证?云南办理ICP经营许可证有哪些要求?
- Oracle的 alter table table_name nologging; 的使用
热门文章
- autosize px转dp_Android 屏幕适配以及autoSize的原理.md
- linux nacos启动_nacos初体验-踩坑与填坑篇
- 转让app后AppStore应用名称下面所有者显示问题
- python数据比例_#python# #数据分析# 性别比例分析
- BCI比赛数据集简介-BCI competition IV 2b
- 像git一样使用AI数据集!免费数据托管工具上线,让模型用「活」的数据集训练...
- Python之父,现在成为微软打工人
- 「Smile」一下,轻松用Java玩转机器学习
- 阿里达摩院实习生立功!何恺明Mask R-CNN精度提升,一半输入数据量就行 | CVPR2020...
- linux中注册系统服务—service命令的原理通俗