0%

这张git语法图的出处已经无从考究了,我存在电脑里很久了,今天看到微博有人求图,我就发出来分享下~需要的右键另存为吧!

昨天换了博客的主题,然后发现页面打开的时候network里有很大一段空白的等待时间,我一直以为是主题用的fontawesome字体渲染太慢或者多说或者GA的网络问题,折腾来折腾去问题还是存在。我最后都快放弃了,不过脑子里依然觉得就是那三者的问题。

然后今天没事,终于有一股劲逼着我去解决这个问题,加上那个等待时间实在是太长,有时候要十几二十来秒,实在受不了了。于是我就去看了原版主题,结果发现没有这个问题。它也用了fontawesome字体渲染、多说和GA。然后我把三者都删了,问题依然存在,过载问题出在别处。我就去排查两者区别发现我自己加了一个highlight的代码格式化组件,我试了一下把这个组件删了,结果。。。完全恢复正常。我当时就无语了,然后去下了最新版的highlight就解决了这个问题。哎╮(╯▽╰)╭,我真是要对fontawesome字体渲染、多说和GA说对不起,莫名其妙背黑锅。

总结,有时候发现一个问题不要理所当然的就认为是哪个地方出了问题而觉得没有办法解决或者不需要解决。很可能这个问题是由于一个你意想不到的地方导致的,而且解决方案非常简单。所以发现问题还是要细心去查找问题原因,这样才能进步啊。

IOS系统的惯性滑动效果非常赞,但是一般我们对div加overflow-y:auto;后是不会出这个效果的,滑动的时候会感觉很生涩。

这时候如果想要我们自己的div有IOS独有的惯性滑动效果,可以有两个选择,一个就是用iscroll插件来模拟,不过现在有个更简单的方法,加个IOS独有的属性:

-webkit-overflow-scrolling: touch;

https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-overflow-scrolling 可以查到此属性的具体文档,属性可以直接对body加或者对需要滑动的div加都可以。

前两天做了个培训,见识了公司自己的GA系统(学名叫“网站数据监控平台”),会上几个大牛争论了半天页面性能的时间参数问题,作为一个菜鸟在下面听的云里雾里,现在抽空查查文档资料,学习一下,做个笔记。

首先我们要了解一个API,即Performance API,它的performance.timing对象算是实现整个性能监控系统的基础,网上一搜,阮大神已经有文章介绍了,我就引用一下Performance的参数解释:

performance.timing对象包含以下属性(全部为只读):

  • navigationStart:当前浏览器窗口的前一个网页关闭,发生unload事件时的Unix毫秒时间戳。如果没有前一个网页,则等于fetchStart属性。

  • unloadEventStart:如果前一个网页与当前网页属于同一个域名,则返回前一个网页的unload事件发生时的Unix毫秒时间戳。如果没有前一个网页,或者之前的网页跳转不是在同一个域名内,则返回值为0。

  • unloadEventEnd:如果前一个网页与当前网页属于同一个域名,则返回前一个网页unload事件的回调函数结束时的Unix毫秒时间戳。如果没有前一个网页,或者之前的网页跳转不是在同一个域名内,则返回值为0。

  • redirectStart:返回第一个HTTP跳转开始时的Unix毫秒时间戳。如果没有跳转,或者不是同一个域名内部的跳转,则返回值为0。

  • redirectEnd:返回最后一个HTTP跳转结束时(即跳转回应的最后一个字节接受完成时)的Unix毫秒时间戳。如果没有跳转,或者不是同一个域名内部的跳转,则返回值为0。

  • fetchStart:返回浏览器准备使用HTTP请求读取文档时的Unix毫秒时间戳。该事件在网页查询本地缓存之前发生。

  • domainLookupStart:返回域名查询开始时的Unix毫秒时间戳。如果使用持久连接,或者信息是从本地缓存获取的,则返回值等同于fetchStart属性的值。

  • domainLookupEnd:返回域名查询结束时的Unix毫秒时间戳。如果使用持久连接,或者信息是从本地缓存获取的,则返回值等同于fetchStart属性的值。

  • connectStart:返回HTTP请求开始向服务器发送时的Unix毫秒时间戳。如果使用持久连接(persistent connection),则返回值等同于fetchStart属性的值。

  • connectEnd:返回浏览器与服务器之间的连接建立时的Unix毫秒时间戳。如果建立的是持久连接,则返回值等同于fetchStart属性的值。连接建立指的是所有握手和认证过程全部结束。

  • secureConnectionStart:返回浏览器与服务器开始安全链接的握手时的Unix毫秒时间戳。如果当前网页不要求安全连接,则返回0。

  • requestStart:返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的Unix毫秒时间戳。

  • responseStart:返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的Unix毫秒时间戳。

  • responseEnd:返回浏览器从服务器收到(或从本地缓存读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的Unix毫秒时间戳。

  • domLoading:返回当前网页DOM结构开始解析时(即Document.readyState属性变为“loading”、相应的readystatechange事件触发时)的Unix毫秒时间戳。

  • domInteractive:返回当前网页DOM结构结束解析、开始加载内嵌资源时(即Document.readyState属性变为“interactive”、相应的readystatechange事件触发时)的Unix毫秒时间戳。

  • domContentLoadedEventStart:返回当前网页DOMContentLoaded事件发生时(即DOM结构解析完毕、所有脚本开始运行时)的Unix毫秒时间戳。

  • domContentLoadedEventEnd:返回当前网页所有需要执行的脚本执行完成时的Unix毫秒时间戳。

  • domComplete:返回当前网页DOM结构生成时(即Document.readyState属性变为“complete”,以及相应的readystatechange事件发生时)的Unix毫秒时间戳。

  • loadEventStart:返回当前网页load事件的回调函数开始时的Unix毫秒时间戳。如果该事件还没有发生,返回0。

  • loadEventEnd:返回当前网页load事件的回调函数运行结束时的Unix毫秒时间戳。如果该事件还没有发生,返回0。

得到了上述的所有时间点后,我们再来看下面这张图(来自W3C),

根据这张图我们基本上就能得到网页的各个时间线了,最后再列举几个比较重要的时间线并做说明:

  • DNS: 从域名解析开始至解析完成的时间 (domainLookupEnd - domainLookupStart)

  • Connect: 从域名解析完成至服务器建立连接完成的时间 (connectEnd - connectStart)

  • Request: 从向服务请求开始至浏览器拿到服务器第一个响应字节的时间 (responseStart - requestStart)

  • Response: 从浏览器拿到服务器第一个字节至最后一个响应字节的时间 (responseEnd - responseStart)

  • Domready: 从发出请求到页面DOM解析完毕,不包括图片的加载 (domComplete - domainLookupStart)

  • Onload: 当页面解析/DOM树建立完成,并完成了诸如图片、脚本、样式表甚至是iframe中所有资源的下载完成。从发出请求到页面完全加载完毕(不包含Ajax时间)(筛选栏显示数据) (loadEventEnd - domainLookupStart)

另附chrome开发者工具对timeline的解释:https://developer.chrome.com/devtools/docs/network#resource-network-timing

如有不正确的地方欢迎指正!

参考:
http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface
http://javascript.ruanyifeng.com/bom/performance.html
http://www.sitepoint.com/profiling-page-loads-with-the-navigation-timing-api/
http://calendar.perfplanet.com/2011/a-practical-guide-to-the-navigation-timing-api/

最近在搭一个angular的开发环境,后端nodejs+express,前端angular+ionic,构建工具是gulp,开始的想法是前端跑一个server,后端跑一个server,做好了之后感觉好麻烦,一次要跑两个server,然后就想着能不能合并,查了下有nodejs直接路由到angular的教程,地址 https://scotch.io/tutorials/use-expressjs-to-deliver-html-files#using-res.sendfile() ,这个不多说,然后遇到的问题是我本来前端用的browserSync,这样方便调试,但是怎么用browserSync来跑nodejs呢。

这里的解决办法就是在nodejs的server和browserSync的server之间加一个nodemon。大致代码如下:

app.js:


'use strict';

// simple express server
var express = require('express');
var app = express();
var router = express.Router();

app.use(express.static('public'));
app.get('/', function(req, res) {
    res.sendfile('./public/index.html');
});

app.listen(5000);

gulpfile.js:


'use strict';

var gulp = require('gulp');
var browserSync = require('browser-sync');
var nodemon = require('gulp-nodemon');

gulp.task('default', ['browser-sync'], function () {
});

gulp.task('browser-sync', ['nodemon'], function() {
  browserSync.init(null, {
      proxy: "http://localhost:5000",
      files: ["public/**/*.*"],
      browser: "google chrome",
      port: 7000,
  });
});

gulp.task('nodemon', function (cb) {
  return nodemon({
    script: 'app.js'
  }).on('start', function () {
      cb();
  });
});

其中nodejs里监听的端口和browserSync里的proxy端口一致,browserSync的port再另设一个。现在跑起来基本上没有问题,后期在做的过程中有问题再修正。

参考:https://gist.github.com/sogko/b53d33d4f3b40d3b4b2e

现在已经过了12点了,今年最后一个工作日已经过去,我是12年过完年来上海实习的,到现在正好3年,三年内我大概搬了五个地方,现在是第三家公司。今年坚持工作到了最后一个工作日,明天早上就要坐车回家了,第一次这么晚才回家过年。都说三年是个坎,感觉应该写个总结,也算是回顾吧,记记流水账,趁现在还记得。

第一份工作是实习工作,大四上学期一个人跑到上海找的,当时真的是个菜鸟,面的几个都是很小的公司,最后挑了一家叫邦蓝决策的,在浦东2号线金科路的浦东软件园3期,过了年就一个人跑去实习了,在附近租了一个700块的很小的屋子。在那家公司做的都算不上前端,美工切图还差不多,一共就3个人,干了两个月就急着走了,感觉再干下去完全浪费时间,学不到什么东西,现在我的简历里都不会去写这家公司。。

第一次跳槽也就从园区里的一栋楼跳到了另一栋楼,沪江网,算是我的第一份正式工作了。当时去面试的时候,感觉,哇!好大,好宽敞,人好多,装修的也不错。面试很容易,做了一个静态页面的作业,然后就过了,大概是12年4月份吧,清明节过后,就去了沪江网实习。真的挺感谢沪江网的,当时一个菜鸟实习生,去了以后有个师傅带着,开始正式的去做一些静态页面,也遇到了专业的设计师和产品。然后是毕业,试用,转正。开始正式的作为一名前端开发。门户站点,网店,移动端H5页面,在沪江主要做一些HTML和CSS的工作,JS主要是写一些交互效果和动画之类的,这段经历让我有了比较扎实的HTML和CSS功底,一些CSS3动画也了解了,但是总体工作量比较轻,开始的时候可能还行,不过这些工作很快就开始重复了,虽然也做过几个大型的特效活动页面,但是对总体提升并不大,特别我的JS方面,提升很有限。当时公司也没有特别厉害的前端前辈,自己当时的见识也太少,感觉遇到了一个瓶颈,13年8月的时候,正好有个同事给我内推了携程,运气非常好的竟然过了面试,然后就去了携程。

携程平台很大,虽然说大公司,在技术的使用上会比较保守,会尽量以稳定为第一前提,但是在深度和细节上,完全不是以前的公司可以比的。以前可能一个项目,做好了就做好了,不存在迭代,顶多会改改小BUG,过个一两个月可能都忘了自己做过这个东西。但是携程不会,它开一个新项目需要考虑很多东西,所以新项目不会开的那么多,主要是已有项目的版本迭代,这样自己负责的项目会一直负责下去,一般情况话不会变,随着版本的迭代,自己就会有了技术积累,而且在项目的优化过程中,各种代码的优化和细节的处理,都让我学到了很多东西。最重要的是开始接触更深层次的JS处理,包括和后台的数据交互,一些数据处理,更细节的JS交互优化等等,这些都是已经没有办法接触到的。后面又开始做移动端的项目,接触了前端MVC框架,hybrid的混合模式APP,对前后端分离有了认识,可以算是接触到了更广阔的前端平台吧。

都说三年是个坎,招聘上的工作经验要求,都是1-3年,3-5年,三年经验为第一个分割,现在我已经过了第一个分割线了,正好前段时间因为一些原因也去面试了几家公司,大概也知道了自己现在处于一个什么水平,大概值多少钱。最后依然选择留在携程,不过几个面试也让我清晰的知道了一些自己的优缺点,特别是面饿了么。。深刻的让我意识到了自己的缺陷,做了这么久的技术,很多东西都还是一知半解,没有自己的想法。这从我写了这么多文章的内容也可以看的出来,我太重视于解决问题的方法,具体的代码怎么写,什么样的问题,用什么样的代码能解决,什么样的BUG,用什么样的方法可以避免。至于为什么这么做,具体的解决思路,所用的语法还有什么用处,都不能清晰的说出来。还有自己去看的一些MVC框架,一些新技术,git之类,都只是看了些皮毛,会写个demo,会一些基本的语法、用法之类的,但是都没有去思考它们的原理,很多对技术的认识都是看的一些博客微博之类的别人的看法见解。没有形成自己的一套想法,这对以后的发展肯定会有致命的影响。

当然这些缺点很多可能也是因为我的职业道路的原因,自己一开始就做的前端,从HTML学起,唯一熟悉的逻辑性语言就是JS,以前在大学的时候,虽然是计算机专业,但是说实话很多课程当时就没学好,现在都忘的差不多了。对一些算法、后台逻辑语言、面向对象编程、数据库的知识都存在缺陷。很多东西以前都理解不了。

所以前段时间开始,我和我的大学舍友合作,准备用nodejs+mongodb自己做一个社交平台,虽然逻辑性语言还是JS,不过总算可以自己去实现一个完整的站点,前后端+数据库都是自己写。当然这次的项目,一定要做到自己写的每一行代码都能理解它的原理,所有用到的语法都要去查一下官方文档的说明,遇到BUG去查解决办法,也要搞通原理。现在经过一个月的努力,这个项目的大致功能也都已实现了,当然这个过程也是真的体验到的nodejs的回调坑,真正的去理解了异步编程。google搜索也用的更溜了,也知道遇到一些组件BUG可以去查github的issues了,官方文档仔细去看比胡乱去搜索解决方法好多了,Stack Overflow也是一个更好的选择。当然这个过程中也算实现了去年给定的目标:搭建一个前端流工作平台。

所以最后也给定下明年的目标吧:

  1. 学会正则;
  2. 理解面向对象编程;
  3. 完成完善mantou项目;

先这样吧,快冻死我了,最后贴下mantou的项目地址:https://github.com/ArayZou/mantou ,新年快乐~

360坑爹浏览器自己提供了一个Meta标签,可以让页面默认选择IE或者webkit内核打开。
在head标签中添加一行代码:

1
2
3
4
5
6
7
<html>
<head>
<meta name="renderer" content="webkit|ie-comp|ie-stand">
</head>
<body>
</body>
</html>

content的取值为webkit,ie-comp,ie-stand之一,区分大小写,分别代表用webkit内核,IE兼容内核,IE标准内核。
若页面需默认用极速核,增加标签:

1
<meta name="renderer" content="webkit">

若页面需默认用ie兼容内核,增加标签:

1
<meta name="renderer" content="ie-comp">

若页面需默认用ie标准内核,增加标签:

1
<meta name="renderer" content="ie-stand">

Read more »

使用JS来判断当前设备的系统,主要用到的就是JS的Navigator对象的userAgent属性。下面列举一些常用设备的匹配规则:


var ua = navigator.userAgent.toLowerCase();
var IsIpad = ua.match(/ipad/i) == “ipad”;
var IsIphoneOs = ua.match(/iphone os/i) == “iphone os”;
var IsAndroid = ua.match(/android/i) == “android”;
var IsWM = ua.match(/windows mobile/i) == “windows mobile”;
var isWeixin = ua.match(/micromessenger/i) == “micromessenger”;
alert(‘isWeixin:’+isWeixin+’,IsIpad:’+IsIpad+’,IsIphoneOs:’+IsIphoneOs+’,IsAndroid:’+IsAndroid);

这里主要是有一个微信的判断,这个在做通过一个地址判断设备来进相应APP下载商店的功能需求时会用到,因为微信屏蔽了安卓的一些下载商店的地址,所以可能需要先判断微信打开来跳微信自己的下载商店,然后再判断设备跳转。
下面再给一个判断PC和移动设备的例子:


if(/AppleWebKit.*mobile/i.test(navigator.userAgent) || /MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent)){
if( window.location.href.indexOf(“?mobile”) < 0 ){
try{
if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)){
window.location.href=”手机页面”;
}else if(/iPad/i.test(navigator.userAgent)){
window.location.href=”平板页面”;
}else{
window.location.href=”其他移动端页面”
}
}catch(e){}
}
}

参考:caibaojian.com/js-mobile-url.html

背景
移动端浏览器在一个通常比屏幕更宽的虚拟“窗口”(Viewport)中渲染页面,从而无需将所有页面都压缩进小屏幕里(那样会把很多没有针对移动端进行优化的站点打乱)。用户可以通过平移和缩放来浏览页面的不同区域。

Read more »