不要再问关于缓存的问题了
背景:
前端 er 需要关注的点,缓存
它在移动端上尤其严重,因为手机随时随地会缓存你的资源,要想清缓存,不像 PC 使用强制刷新,还要手动找到浏览器的缓存,有时候还要重启等
所以 用实践理解缓存机制 写下此文记录
为了对比理解本文会涉及到
- DNS 缓存
- CDN 缓存
- 浏览器缓存 (HTTP 缓存)
2018 写在年终的话
2018 年终总结
搭建服务器亲自体验跨域
前端防刷实现
前段时间写了前端防刷逻辑 作此记录
当时的需求
防刷逻辑 1 24 小时内 一个手机号只能提交三次 第四次提交的时候 提示 已提交成功 请耐心等待 400
防刷逻辑 2 24 小时内 提交三个手机号 提交第四个时 提示 401
addEventListener 中的 passive 用法
引出问题
一个很简单的需求 页面有一张小图 点击是个 swiper 实现的图集 同时有一个灰色的蒙层 蒙层底部页面不可滑动 关闭蒙层 页面可恢复正常
实现方式
1 | function bodyScroll(event){ |
移动端的效果如下
android
ios
我不知道为什么无效 直到我在模拟器上看到了
啊哦 报错了🦢
Unable to preventDefault inside passive event listener due to target being treated as passive
来自 google 的解释 https://developers.google.com/web/updates/2017/01/scrolling-intervention
大概的意思是说
1 | 由于浏览器必须要在执行事件处理函数之后,才能知道有没有调用过 preventDefault() ,这就导致了浏览器不能及时响应滚动,略有延迟。 |
这就导致了这个问题
1 | 如果在以上这 3 个元素的 touchstart 和 touchmove 事件处理函数中调用 e.preventDefault() ,会被浏览器忽略掉,并不会阻止默认行为 |
所以出现了以上视频中问题
解决方案
那么我们如何来解决这个问题 即不要让浏览器忽略掉 e.preventDefault ()?
- window.addEventListener(‘touchmove’, func, { passive: false })
设置 passive: false 之后的结果
android
ios
浏览器
问题完美解决
1 | 你看到这里可以结束了 如果你还想再了解一点点 |
addEventListener(type, listener[, useCapture ])
addEventListener(type, listener[, options ])
1 | 扩展新的选项,从而自定义更多的行为,目前规范中 options 对象可用的属性有三个: |
addEventListener(type, listener, {
capture: false, 等价于 useCapture 默认值 false
passive: false, 是否让阻止默认事件失效 true: 失效 false:不失效
once: false // 表明该监听器是一次性的,执行一次后就被自动 removeEventListener 掉,还没有浏览器实现它 默认值 false
})
1 |
|
你可以直接省略第三个参数
window.removeEventListener(‘touchmove’, func)
如果添加了 第一个参数 capture 可以这样移除
window.removeEventListener(‘touchmove’, func, true)
window.removeEventListener(‘touchmove’, func, {capture :true})
为什么会有 passive 这个概念
像这样儿的代码
1 | document.addEventListener("touchstart", function(e){ |
由于 touchstart 事件对象的 cancelable 属性为 true,也就是说它的默认行为可以被监听器通过 preventDefault () 方法阻止,那它的默认行为是什么呢,通常来说就是滚动当前页面(还可能是缩放页面),如果它的默认行为被阻止了,页面就必须静止不动。但浏览器无法预先知道一个监听器会不会调用 preventDefault (),它能做的只有等监听器执行完后再去执行默认行为,而监听器执行是要耗时的,有些甚至耗时很明显,这样就会导致页面卡顿。视频里也说了,即便监听器是个空函数,也会产生一定的卡顿,毕竟空函数的执行也会耗时。
有 80% 的滚动事件监听器是不会阻止默认行为的,也就是说大部分情况下,浏览器是白等了。所以,passive 监听器诞生了,passive 的意思是 “顺从的”,表示它不会对事件的默认行为说 no,浏览器知道了一个监听器是 passive 的,它就可以在两个线程里同时执行监听器中的 JavaScript 代码和浏览器的默认行为了
一个问题引出的 pushState 用法
引出问题
为什么有这篇文章.
最近的开发中遇到这么一个问题
如下图
扫码进入网页 点击弹出覆盖整个手机屏幕的层 此时点击浏览器的返回 会直接回退到之前扫码页面
其实 这个逻辑很合理 因为它没有历史记录 没有所谓的上一个页面 程序上是合理的
但用户体验无疑是差到极致
对于用户来讲 可能我只是想把当前的弹层关掉而不是退出网页
那么如何解决呢?
解决方案
没有历史记录 那我们就手动造出来一条 “历史记录”,让程序的返回时 能够有迹可循
最终效果
相关代码
1 | componentDidMount(){ |
History
DOM 中的 window 对象通过 window.history 方法提供了对浏览器历史记录的读取,让你可以在用户的访问记录中前进和后退
从 HTML5 开始,我们可以开始操作这个历史记录堆栈
前进 window.history.forward();
后退 window.history.back();
向前移动 N 页 window.history.go(-N);
向后移动 N 页 window.history.go(N);
你甚至可以通过检查浏览器历史记录的 length 属性来找到历史记录堆栈中的页面总数window.history.length
HTML5 history 新特性 pushState、replaceState
HTML5 引入了 histtory.pushState () 和 history.replaceState () 这两个方法,他们允许添加和修改 history 实体。同时,这些方法会和 window.onpostate 事件一起工作,关于 window.popstate 可参考 window.popstate
pushState:向 history 添加当前页面的记录 使用 history.pushState () 方法来修改 referrer
replaceState:和 pushState 的用法完全一样,区别就是它用于修改当前页面在 history 中的记录
一个🌰
1 | 假设http://10.70.134.53:3000/opt/financial 控制台执行了JS |
总结:
关于 popstate 事件 需要注意的几点
- 调用 history.pushState () 或者 history.replaceState () 不会触发 popstate 事件.
- popstate 事件只会在浏览器某些行为下触发,比如点击后退、前进按钮 (或者在 JavaScript 中调用 history.back ()、history.forward ()、history.go () 方法).
也就是说 要触发该事件 你需要两步
- 添加并激活一个历史记录条目 (history.pushState)
- . 改变历史记录条目 (用户行为,比如后退,前进)
揭秘 setState 机制
前言:state 是 react 中重要的概念, react 是通过管理状态来实现对组件的管理,那么 react 是如何控制组件的状态 又是如何利用状态来管理组件的呢?
我们所知道的版本 大概是 通过 this.state
来访问 state
,通过 setState()
方法来更新 state
,当 this.state()
被调用的时候 React
会重新调用 render
方法来重新渲染 UI
那好的 先来看一道题吧
1 | export default class SetState extends React.Component { |
这道题的答案是 0 0 1 1 2 3 4
假如结果与你心中的答案并不完全相同,那么你应该感兴趣这背后究竟发生了什么.
彻底理解 js 是如何工作的
曾经 你一定遇到过类似这样儿的题目
1 | console.log('script start') |
如果你很轻松的答对并且能说出原理 那么恭喜你,倘若有些疑问,那么读完这篇文章,你一定会彻底搞懂它的运行原理。