谈谈StorageEvent

栏目: Html5 · 发布时间: 6年前

内容简介:纷纷红紫已成尘,布谷声中夏令新。夹路桑麻行不尽,始知身是太平人。 ——宋.陆游 《初夏绝句》我们在开发多Tab应用时候,常常会遇到多个Tab状态同步的问题。想象如下场景:用户主界面,显示用户购物车内待结算的商品总数。此时,用户可能打开多个Tab。当用户添加新商品到购物车的时候,需要更新购物车的数量。
谈谈StorageEvent

纷纷红紫已成尘,布谷声中夏令新。夹路桑麻行不尽,始知身是太平人。 ——宋.陆游 《初夏绝句》

我们在开发多Tab应用时候,常常会遇到多个Tab状态同步的问题。

想象如下场景:用户主界面,显示用户购物车内待结算的商品总数。此时,用户可能打开多个Tab。当用户添加新商品到购物车的时候,需要更新购物车的数量。

谈谈StorageEvent

此时,当前页面需要向服务器发起请求,在得到添加成功响应的时候,可以更新用户界面。为了兼顾体验和可靠性,如果确信添加成功概率比较高的时候,也可以先更新界面,当多数返回错误的时候,可以给用户界面做状态回滚。为了下次展示方便,我们还会把这个数据写到LocalStorage里面。用户再次打开时候,可以优先从localStorage中取值。

当前页面解决了,那么如果同时打开多个Tab该如何解决呢?这里使用StorageEvent可能是一种代价较小的解决方案。

StorageEvent是什么呢?

  1. 是一种Event,可以通过标准的Event监听器操作。
  2. 当storage变化时候,事件会被派发到所有同域下的其他页面。
  3. 触发变化的当前页面,没有事件派发。

这里有一个简单的示例可以展示这个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即可。

参考资料

  1. developer.mozilla.org/en-US/docs/…
  2. www.cnblogs.com/cczw/p/3196…

关于奇舞周刊

《奇舞周刊》是360公司专业前端团队「奇舞团」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。

谈谈StorageEvent

以上所述就是小编给大家介绍的《谈谈StorageEvent》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

About Face 3

About Face 3

Alan Cooper、Robert Reimann、David Cronin / John Wiley & Sons / 2007-5-15 / GBP 28.99

* The return of the authoritative bestseller includes all new content relevant to the popularization of how About Face maintains its relevance to new Web technologies such as AJAX and mobile platforms......一起来看看 《About Face 3》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具