前言
- 常网IT源码上线啦!
- 本篇录入吊打面试官专栏,希望能祝君拿下Offer一臂之力,各位看官感兴趣可移步🚶。
- 有人说面试造火箭,进去拧螺丝;其实个人觉得问的问题是项目中涉及的点 || 热门的技术栈都是很好的面试体验,不要是旁门左道冷门的知识,实际上并不会用到的。
- 接下来想分享一些自己在项目中遇到的技术选型以及问题场景。
我一直觉得人应该先了解自己,先认识自己是什么样的人,想过什么样的生活。
可是行动是产生结果的唯一途径。
你有这个想法,你想去认识自己,可能这个想法,世界上有一万个人想到,真正去坐的只有一千个人,找到自己的只有一百个人,我们先当这一千个,再当这一百个人。
大家知道,这里是哪里嘛
一、前言
今天像往常一样,开开心心的打代码编程。
突然产品说:这个加入购物车之后,右侧要实时显示数量,并且在页面刷新的时候,依然保存起来。
于是便有了今天这篇文章,一起来探讨一下。
当然,你也可以当做实操性面试题。
二、分析
后端同学说:这个应该不用调接口,保存吧。
霸气回复:并不需要,我大前端足矣!
当然,在说之前,我们是有底气的,相信大家第一想到就是:localStorage。
我们知道,localStorage的set完值之后,不会像观察者模式有通知机制的。
上个月去考了软考,猛学设计模式,之前看是一定的了解,现在学了这么多年前端,再去看,又有不一样的思考。
既然localStorage没有提供相关事件,那我们便无中生有。
于是我们需要借用storage
事件来实现。
这样,当一个组件(例如 A 组件)设置了 localStorage
的值时,另一个组件(例如 B 组件)能够接收到该变化。
而这里,我们需要先封装 localStorage.setItem 方法。
三、setItem
首先,我们封装 localStorage.setItem
方法,当设置 localStorage
的值时,手动触发 storage
事件,以便其他组件能接收到更新。
utils/localStorage.js
const originalSetItem = localStorage.setItem;
// 封装 localStorage.setItem 方法
localStorage.setItem = function(key, value) {
// 调用原始的 setItem 方法
originalSetItem.apply(localStorage, arguments);
// 触发 storage 事件,通知其他页面
const event = new StorageEvent('storage', {
key: key,
newValue: value,
oldValue: localStorage.getItem(key),
storageArea: localStorage,
});
window.dispatchEvent(event);
};
监听 storage
事件
在 Vue 组件中,我们可以使用 window.addEventListener
来监听 storage
事件,并在事件发生时执行相关的回调函数。
四、代码实现
A页面
加入购物车相关逻辑
change(data) {
const appliedList = JSON.parse(localStorage.getItem('appliedList') || '[]')
// 选中
if(data.isSelectCart) {
const _index = appliedList.map(a => a.id).indexOf(data.id)
appliedList.splice(_index, 1)
} else {
appliedList.push(data)
}
this.$set(data, 'isSelectCart', !data.isSelectCart)
localStorage.setItem('appliedList', JSON.stringify(appliedList))
}
B页面
A页面setItem的时候,会触发我们重写的localStorage,StorageEvent触发 storage 事件,通知其他页面。
而在B页面的代码监听:
mounted() {
// 监听 storage 事件
window.addEventListener('storage', this.handleStorageChange)
// 初始时检查 localStorage 是否已经有值
const storedData = localStorage.getItem('appliedList')
if (storedData) {
const appliedList = JSON.parse(localStorage.getItem('appliedList') || '[]')
this.badge = appliedList.length // 显示
}
}
handleStorageChange(event) {
if (event.key === 'appliedList') {
const appliedList = JSON.parse(localStorage.getItem('appliedList') || '[]')
this.badge = appliedList.length // 显示
}
}
五、上线
于是,你在本地调试了,发现效果确实是达到了,A页面set之后,B页面也确实收到了消息更新。
欣喜若狂部署到线上,测试说,你这也没实现啊。
是的,我早知道了,因为StorageEvent该事件能够让多个页面(或不同的标签页)在同一浏览器中相互通信,从而实现跨标签页的数据同步。
注意只是在不同标签才会通知,当前标签是不会更新的。
所以,我们还要借着vuebus去做更新通知。
这个比较简单,如果有不明白的,可以留言讨论。
六、StorageEvent
来都来了,顺便了解一下StorageEvent。
该事件能够让多个页面(或不同的标签页)在同一浏览器中相互通信,从而实现跨标签页的数据同步。
StorageEvent
事件对象包含多个关键属性,用来描述存储的更新情况:
- key:表示被修改的 localStorage 或
sessionStorage
项的键名(即字段名)。当调用clear()
清空所有存储项时,key
的值将为null
。 - newValue:表示存储项的新值。如果是通过
removeItem()
删除某项数据,newValue
将为null
。 - oldValue:表示存储项更新前的旧值。如果使用 setItem() 设置新值,则
oldValue
为更新前的值。如果是通过removeItem()
删除某项,oldValue
将是被删除的值。 - url:触发该事件的文档的 URL,指明了存储操作发生的页面来源。
- storageArea:指向 localStorage 或 sessionStorage 对象,表示当前操作的是哪个存储区域。这个值通常为 localStorage 或 sessionStorage,取决于使用的存储类型。
StorageEvent
事件通常用于在同一浏览器中不同标签页之间同步数据。
至此撒花~
后记
我们在实际项目中或多或少遇到一些奇奇怪怪的问题。
自己也会对一些写法的思考,为什么不行🤔,又为什么行了?
最后,祝君能拿下满意的offer。
我是Dignity_呱,来交个朋友呀,有朋自远方来,不亦乐乎呀!深夜末班车
👍 如果对您有帮助,您的点赞是我前进的润滑剂。