Chrome inspect devices 打开空白页面的问题
最近换了个新电脑,发现连手机调试 H5 页面的时候,chrome 可以发现设备,但是点击inspect
按钮之后弹出的调试窗口是一个空白页面。
这问题搞得人很懵逼,一通搜索之后发现 chrome 项目中的一个 issue 提到:
致中国同胞:如果你按照要求操作最后却得到一个空窗口,翻墙后再试试。不用谢。
无语,翻墙后搞定。致所有中国同胞,遇事先想想是不是墙挡住了你。
经试验,这个只会在第一次使用 Chrome 调试设备时候出现,应该是第一次调试的时候Chrome会从 Google 那里加载 ChromeDevTool 的页面文件到本地并且将其缓存起来。加载过之后就不会再出现这个情况了。
参见
issue#14
active 伪类在 iOS 中不触发的问题
点击按钮的时候通常会为按钮提供一个按压高亮的处理,这时候我们就会用到 :active
伪类
1 | button:active { |
在安卓手机上当我们按下按钮的时候,:active
的表现和我们的预期是一致的,按钮会呈现按压态。但是在 iOS 设备上却没有效果。
查阅了一下文档,发现上面写着这句话:
[1] Safari Mobile 默认不使用:active 状态,除非元素上或
上有一个touchstart 事件处理器。
也就是说在 iOS 设备上只有我们监听了 body 的 touchstart 事件,:active
才会有效果。所以我们这样做:
1 | document.body.addEventListener('touchstart', () => {}); |
添加上述代码后,:active
就可以被正常触发了。
JS 将内容导出为文件并下载
原理就是创建一个<a>
标签,创建一个 blob 对象,然后用 js 触发点击事件来下载 blob 对象即可。
1 | const content = 'file content' |
谷歌不断要求人机验证的解决方案
最近发现通过我自己搭的 ss 访问 google 也会出现要求人机验证的页面,怀疑是有人在 vps 所在的网段上面搞爬虫什么的,导致 google 将网段加入了黑名单。不过我发现验证页面的 url 都是以 ipv4 开头的,说明可能是 ss 服务器所在的 ipv4 地址被 google 加入了黑名单,但是 ipv6 可能是没有被限制的。我向 ss 服务器的 /etc/hosts 追加如下的配置:
1 | 2607:f8b0:4005:801::200e google.com |
这样可以强制使用 ipv6 地址来访问 google。验证码就会消失了。
ReactNative 的远程调试原理
众所周知,RN 提供了一个远程调试的功能,在调试的过程中可以自动刷新资源,这极大地方便了开发的过程。但这个方便的功能是如何实现的呢?开发机是如何得知需要从哪里拉取资源的呢?这两天正在搞 RN 方面的研究,正好研究了一下这个问题,感觉这是一个很好的调试思路,以后可能会有用,先在这做个记录。
在 react-native-xcode.sh 脚本中使用下面的代码获取了作为 debug server 的电脑的 IP 地址IP=$(ifconfig | grep 'inet ' | grep -v 127.0.0.1 | cut -d\ -f2 | awk 'NR==1{print $1}')
然后使用如下语句将 IP 地址写入 ip.txt
文件中,然后将这个文件放到 app 的资源目录下
echo "$IP" > "$DEST/ip.txt"
然后使用 Xcode 构建 APP 的时候,这个 ip.txt
文件会作为资源被打包进 app 安装包中。当 ReactNative 程序开始运行的时候在 RCTBundleURLProvider
的 guessPackagerHost
方法中读取这个文件以获取 IP 地址,然后从这个 IP 地址的 debug server 上获取 jsbundle
1 | - (NSString *)guessPackagerHost |
详解 Angular2 的变更检查原理
相比 Angular1 而言 Angular2 的变更检查机制更加透明,更加可预测。但是在使用 Angular2 开发的过程中依然存在着一些场景(比如性能优化)需要我们更深入的了解在框架的底层究竟发生了什么。
本文包含如下内容:
- 变化产生于异步操作
- 为浏览器打补丁
- Zone.js
- 补丁是如何工作的
- Angular2 中 Zone 的应用
- 自动检查数据变化
- 可选的变更检查
- Angular2.x 变更检查工作原理
- Angular 的默认变更检查如何工作
- OnPush 模式
- 总结
- 参考资料
本文的描述基于 Angular 2.4.9 版本
使用RxJS来构建响应式应用
使用内存缓存需要注意的一个问题
最近做需求的时候遇到一个坑,对这个问题的思考在这里记录一下
在应用中为了使得数据尽快展示出来,在网络请求的数据回来之前都会先显示内存中缓存的数据。存取缓存的方法大概是这个样子
1 | var setCacheInfo = function(key, value) { |
cacheWebData
是一个内存中的对象,读取缓存就是直接反悔了对象中 key
对应的 value
。然后将取出来的值进行传递。
先说下问题的现象,在调试的时候我发现,从内存缓存中取出来的值会莫名其妙的改变。比如:在 A 页面中使用key
取到的值是{a:1,b:2}
,但是在进入过 B 页面之后同样使用key
取到的值却变成了 {a:1,b:2,c:3}
,这过程中没有调用setCacheInfo
方法来修改缓存中的值。
难不成他还自己变了?
这显然是不可能的,查找了好半天,我发现取出这个缓存的值以后,这个值被传递了好几层,最终被 $.extend(obj,{c:1})
了一次。这一改不要紧,由于传递的是缓存中对象的引用,这下直接将缓存里面的值也修改了,到下次再使用缓存的时候取出来的值就已经不是原来的值了。然而在 extend 的地方,使用者是完全不知道这个对象引用的是什么地方的数据,这里是一个隐患。
避免出现这个问题有三个办法;
- 将
getCacheInfo
方法改为以下的实现
1 | var getCacheInfo = function(key) { |
也就是将传出的值进行深拷贝,切断与缓存内部对象的引用关系。
2. 模仿 localStorage 的接口,令缓存对象只接受字符串类型的 value,那么读取方法要这样实现
1 | var setCacheInfo = function(key, value) { |
- 直接规定不允许直接 extend 对象…,或者只允许为空对象扩展属性(并不能完全排除隐患)
1 | $.extend({}, obj, {c:3}) |
于是我想看下 jquery,node-cache 之类的框架中是如何处理缓存读写的。
jQuery.data 的实现如下:
1 | get: function (owner, key) { |
同样存在这个问题。
node-cache 的实现:
1 | exports.get = function(key) { |
蛤,也有这个问题。。
看来主流框架告诉我们是不应该随意地对对象进行扩展了,不然一不留神就会出现这种问题…想要防患于未然最好还是使用深拷贝或者只存字符串类型值的方法吧。