谈谈StorageEvent

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

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

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

我们在开发多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 (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中获取对应的值,并手动调用一下即可。

参考资料

  1. https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event
  2. https://www.cnblogs.com/cczw/p/3196195.html

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

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

自品牌

自品牌

陈为、孙郁婷 / 机械工业出版社 / 2015-9-7 / 39

移动互联网来势汹涌,让品牌重新回到人的时代。微信旗帜鲜明地宣示,“再小的个体也有自己的品牌”。《自品牌:个人如何玩转移动互联网时代》作者历经一年,深度访谈10位嘉宾,挖掘其品牌与商业成功密码。吴晓波、雕爷、罗永浩、鬼脚七、马佳佳……这些商业新浪潮中的探路者与领军者,要么是传统领域的老将,要么是新领域里的先锋,但都能以新媒体为载体,构建个人品牌,打造商业生态,抓住互联网的时代红利,顺风而起,顺势而为......一起来看看 《自品牌》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码