神棍之心,人皆有之。最近在看数学之美,简而言之,科学家眼里,一切都能拟合成函数,就看能不能把参数找出来把因数算出来。不过大家还是喜欢凭借直觉做出各种预测,考验自己的判断力。我也准备写几篇日志,分析一下当今IT乃至TMT的趋势,等到明年这个时候翻出来,看看能说对多少。
作者: meathill
-
诡异BUG之:IE下表单必须提交两次
做前端遇鬼是常事儿,比如今天,就遇到个:
- IE6~10
- jQuery 1.8.3
- Backbone 0.9.2
- HTML5头
- 一个
Backbone.View,内部有一个form,View托管form的submit事件,根据class和action进行不同的操作,或者验证数据提交表单 - 第一次提交,验证通过,
return true,没反应 - 第二次提交,验证通过,
return true,表单提交 - 其它浏览器表现正常
提炼这些Bug描述就花了不少时间,反复Google也没有什么结果。比如,StackOverflow上类似问题的解答是:
submit原本不会冒泡,所以应该直接侦听form;但实际上jQuery1.4之后已经支持submit事件的托管了,我的实验也支持这个结果。至于导致问题的原因,我还没想明白也没测出来,留着以后再做吧。最后用Hack的方式暂时解决:
if ($.browser.msie && isIEFirstSubmit) { isIEFirstSubmit = false; setTimeout(function () { form.submit(); }, 50); }有了解这个的高人还请不吝赐教。有感兴趣的同学可以去试试:http://www.dianjoy.com/dev/#/user/updateuser
-
原来早期Android的WebView真的很奇葩
以前没在Android下做过原生HTML开发,所以一直觉得大家的吐槽很莫名其妙——不同于桌面错综复杂的环境,高度统一的webkit内核浏览器能整出什么幺蛾子来?结果这次遇到了,才发现原来早期Android系统的WebView真的很奇葩。
先是有一块文字,可能比较长,我就在作容器的
div上写样式为overflow:scroll,以为这样就能用手指触摸滚动了,拿来小米1S一试,通过。结果后来同事找来,说他的手机不行。研究半天,在StackOverflow上看到Android 3.0之后才开始支持触摸滚动,想在2.x系统上实现还得自己写JS实现。一看他的手机,2.3.5。OK,写JS嘛,好说。事先我已经知道触摸事件的触发机制,所以很自然的就去侦听
touchstart,touchend,touchmove。结果,不行,滚不起来。我以为自己记错了,去MDN上查了查,没错;又猜是事件用错了,尝试touchleave和touchcancel,也不行;2.x的系统不能装Chrome,测试也不好搞。后来终于通过输出发现,touchmove只触发一次,然后Google之,原来Android设计的机制就是只触发一次,想要自主控制事件结束的时机只能event.preventDefault()。这……难道touchmove不是对应mousemove么?只这两点就花了我不少时间,不知道还有没有其它的坑。反正做完这个需求我不禁感慨,早期Android的WebView真的很奇葩啊。
PS:这篇博文应该早于上一篇,换言之就是这个时候我为了在本地调试打开了“Emulate Touch Events”开关的。
-
一个诡异问题的排查
这个问题本身其实不能称之为问题,记下来只是我觉得排查经历挺典型的,值得分享。
先说下我的环境:MacOS 10.8.2 + Chrome 23.x + Bootstrap 2.2.1 + jQuery 1.8.2。事情是这样的,我本来在开发一个新功能,顺便把老页面重构一下,貌似一切正常。重构完毕后,我想随手测试一下重构后的页面,发现下拉菜单竟然不能点击了,或者说,点击完全失效了。
这让我很恐慌,因为类似的重构过程我近段时间来做的不是一次两次,这次我应该没有任何冒险的改动才是。这种情况下出现的Bug,一般都很棘手。于是,我打开以前的某个页面——同样经历了重构,但是通过了测试,并且在一顿时间的使用中完全没有问题——发现里面的下拉菜单同样点击失效了。于是,真正的排查开始了。
-
INFINITE会阻碍JavaScript数组排序
如题。代码就是最简单的,一个装满对象的数组根据某个值排序:
sortArray.sort(function (a, b) { return a[key] - b[key]; });开始某些对象的值是NaN,我试了下,排序正常,结果稳定,就没再管。
今天突然发现排序失败,没有报错,查了半天不见异常,只好下手排查一切可能因素。第一个就是
INFINITE,翻找MDN无果,想办法过滤掉,排序正常。想来负无穷也会影响,所以先判断除数不能为0 还是很有必要的啊。
-

MySQL 同表复制数据
我觉得再这么下去,我真敢说我写过PHP了……
需求很简单,在同一个表中复制数据。以前的代码是在PHP里先
select *,然后extract成变量,再组合成一个大 sql,最后插入。我觉得这样不好,首先要执行两次 sql,其次写那么一大篇 sql 也挺麻烦的。于是研究了下,发现并不复杂,这里总结一下:如果是从别的表里导入数据,可以这样写:
INSERT INTO `table` SELECT * FROM `table2` WHERE `id`=1如果是同表,并且表里没有主键,这样也好使;但是有主键的话,会被告知主键重复,这个时候就只能把字段都写出来了:
# 假设表结构为 id, col1, col2, col3 INSERT INTO `table` SELECT NULL, col1, col2, col3 FROM `table` WHERE `id`=1这里字段的顺序很重要,要参照表的顺序来写(我是用 MySQL Wordbench 连上库,然后用
Alert table看的);不过好处在于,如果我们需要更改其中某个字段的值,只要在 sql 里直接写就好。比如我们复制后想交换后两个字段,或者改变某个字段的值,就可以这样:# 假设表结构为 id, name, age, sex # 交换age和sex INSERT INTO `table` SELECT NULL, `name`, `sex`, `age` FROM `table` WHERE `id`=1 # 更改某字段的值:将复制得到的name加上copy_前缀 INSERT INTO `table` SELECT NULL, CONCAT('copy_', `name`), `age`, `sex` FROM `table` WHERE `id`=1而
id这种自增的主键,直接插入 NULL 就可以了,MySQL 会自动帮我们补全(如前几段所示)。同时插入多条数据也很简单,这样即可:
# 假设表结构为id, name, age, sex # 复制 id<10 的字段,加上copy_标识 INSERT INTO `table` SELECT NULL, CONCAT('copy_', `name`), `age`, `sex` FROM `table` WHERE `id`<10实话实说我不太懂MySQL,不过这样写我觉得有几个好处:
- 省事儿,可以不再把变量一一抄上
- 可以一次复制多条数据
- 只执行一行sql,速度应该会更快
-
使用免费CDN加速JavaScript的加载
做前端的,基本都会用上各种开源的框架、类库。在项目中引用它们,就可能需要把用到的文件纳入版本库,这样每次类库更新,我们也得跟着更新文件,比较麻烦。而且,我们知道,浏览器对同一个域名下的资源同时加载的数量是有限制的,加载页面时光类库的CSS和JS就得搞半天,整体速度也会被拖累。
好在很多仁人志士已经提供免费的CDN分流服务,帮助我们托管类库。我用到的主要有这些:
jQuery
jQuery流行度毋庸置疑,所以微软和Google都提供了jQuery系列,包括UI和Mobile的CDN,Google的CDN还包括一些其它类库,比如prototype和Mootools等。
微软:http://www.asp.net/ajaxlibrary/cdn.ashx#jQuery_Releases_on_the_CDN_0
Google:https://developers.google.com/speed/libraries/devguide
Bootstrap
Bootstrap是由来自twitter的两名“Nerd”工程师创建的前端框架,非常棒,刚好覆盖了网站页面所需,组合使用无往不利。BootstrapCDN为我们提供了相应的服务:
Underscore和Backbone
cdnjs.com 这种业界良心提供了最丰富的CDN资源,还包括了每种类库的官网或者其在github上的链接(好吧,很多时候他们就是一回事儿),我觉得甚至可以把这个站点当成学习的出发点。肉大师项目中用到的Underscore和Backbone就取自这里,感谢他们。
值得一提的是他们的域名也很好记~
-

JS加分号的理由
JavaScript界关于是否应该加分号的争论由来已久。在我看来,这就跟《格利佛游记》中“大头党”、“小头党”一样,纯粹蛋疼,一群衣食无忧的达人,领着一群不明所以的小白战来战去。
吐槽时间结束。我本来对于分号不是很在意,一般每行都加,函数和条件后面不加。后来学会了“模块化”的写法——即每个逻辑用一个立即执行函数——
(function () { // 逻辑主体 })()包裹,就开始混用。一直没遇到什么问题,直到今天是 Ant + Closure Compiler 编译部署肉大师,莫名其妙的挂掉了。排查半天发现是分号的问题。原来的代码可能是这个样子:
// 模块1 // 前面有若干代码 var Manager = { prop: '', method: function () { } } // 模块2,开头是个立即执行函数 (function () { // 代码 })()<经过压缩后变成这个样子:
// }}(function 那里,会被当成一个函数来执行,于是整体的解析就会出错了 var Manager = {prop: '',method: function () { // code }}(function () {// 代码})()这时只要给每个文件的末尾加上分号,就解决了。还有种做法,就是在开头加上分号,很多开源代码也是这样做的:
;(function () { // code })()如此,便给JavaScript代码写分号添了一个理由。
-
Surface使用心得
没找到说明,自己摸索了点,记录下来。
-
新玩具:微软Surface
微软第一次放出Surface消息的时候,我就非常期待。无论是造型、外观、Windows8、号称原生的HTML运行环境,都非常吸引我,尤其是充当了键盘的保护套。预售开始,我就迫不及待的在线上订购了;后来得知当天晚上12点首发,如果现场买还送个鼠标,而且选址又是离我家非常近的联想桥苏宁,我立刻决定把线上的退了,然后跑去现场购买。