Giter Site home page Giter Site logo

blog's Introduction

Hey there! I'm Yves.

👨🏻‍💻  About Me

  • 🍒   A post-89s person who loves software development.
  • 🤔   Exploring new technologies and developing software solutions and quick hacks.
  • 👩‍💻   Work for 10+ years, including javaweb, node and front-end.
  • 💼   Responsible for front-end team technology and management.
  • 🌱   Learning more about Cloud Architecture, Systems Design and Artificial Intelligence.

🛠  Tech Stack

  • 🌐   HTML5 CSS JavaScript TypeScript Node.js React Vue Electron

  • 🛢   MySQL MongoDB

  • ⚙️   Git GitHub Markdown

  • 🔧   Visual Studio Code

  • 🖥   Photoshop


    

blog's People

Contributors

coolfishstudio avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

blog's Issues

[原发布时间: 2016-02-25] 近几年前端技术盘点以及2016年技术发展方向

Web 发展了几十个春秋,风起云涌,千变万化。我很庆幸自己没有完整地经历过这些年头,而是站在前人的肩膀上行走。Web 技术发展的速度让人感觉那几乎不是继承式的迭代,而是一次又一次的变革,一次又一次的创造。这几年的前端,更为之甚!

我从 12 年底开始接触前端,12 年之前的前端发展情况只能从上一辈的笔触中领会。本文会盘点从 09 年开始到 15 年间前端技术的革新,同时也会从多个角度,解读近几年前端技术发展的潜在因素,其中穿插了若干对前端演进的拙见,难免会有错误和疏漏,望读者可以补充和斧正。

那些年,一度追捧,一度放弃

下面,花一些篇幅简单回顾下 09 年到 15 年前端的发展历程(感谢@法海 师兄对文章部分内容的校稿,很多技术出现的时间有所偏差,但不影响阅读)。

09 年,基础类库完善,寻求突破

09 年之前,JavaScript 还处于对自身语言的完善过程中,而到了 09 年,JavaScript 类库已经颇为成熟,jQuery/Prototype/Dojo 等都已经发布了好几个 stable 版本,各大类库也是相互吸收优点,不断完善并提高自身性能,然而功能上已经没有太多增加的势头。部分框架开始了**上的转变,更加注重前端开发的组织和结构,条理性强了很多,如 YUI 等。

从 ECMAScript 规范的争执,开启了浏览器引擎大战,各大厂商也趁机瓜分 IE 份额,Chrome 和 Firefox 在这场战役中取得大胜,V8 也敲响了前端的大门。为了迎合市场的激烈竞争,IE 开始了升级之旅,09 年初发布 IE8,全面兼容 CSS2.1。

而此时,Node.js 和 3G Mobile 这两只巨兽开始浮出水面,Web 标准也开始向 HTML5、ECMAScript5.0 靠拢。

10 年,看齐标准,关注 Web 性能

毫无疑问,这一年,各大巨头都看清了 HTML5 是 web 发展的未来,在保留原来前端技术的状态下,都簇拥着拉扯 HTML5 的裙摆。富客户端应用也在这一年蓬勃生长,ExtJS/Dojo 摇身变为企业级框架,各类组件化概念和产品如约而至。

延续着 09 年的变化,10 年的前端显得颇为沉寂,然而在标准的运用和推动上,各大厂商也是十分卖力。IE 9 出来了预览第三版,iPhone 的 Safari 已经能够支持众多 HTML5 内容:Canvas/Video/Audio/Geolocation/Storage/Application Cache/Web SQL Database 等。

W3C 宣布成立 Web 性能工作组,Google 和 Mozilla 纷纷推出应用商店,浏览器调试工具也丰富了起来,人们开始更多地关注开发体验和性能问题。

11 年,HTML5 扛大旗,Flash 堪忧

2011 年 HTML5 的技术发展和推广都向前迈进了一大步,语义明确的标签体系、简洁明了的富媒体支持、本地数据的储存技术、canvas 等等各类技术被广泛应用。这一年,很多 web 开发者也面临一项技术的抉择,HTML5 or Flash?从 Flash Player 11.1 开始,Adobe 不再继续开发面向移动设备浏览器的 Flash 插件,积极投身于 HTML5,这意味着 Flash 技术的凋零。

这一年,HTML5 游戏火爆到了一个高潮,移动端开发工具和调试工具也日益成熟。jQuery 已经成为大小公司日常开发的标配,成千上万的 JQ 插件让网页开发变得尤为轻松,而随之而来的也是页面的臃肿和性能调优的深入探索。

Node.js 已经悄然崛起,在 github 上的访问量已经超过了 Rails,国内的云应用开始尝试使用 Node.js,Node.js 相关工具也纷纷出来。

12 年,响应式开发,工程化推进

随着硬件技术的发展,各手机厂商又开始*动起来,为了占有更多的市场,不断提高产品的性价比,体验也得到了不断的优化。借着先前两年 HTML5 刮起的东风,移动端上的 web 开发也颤抖了起来。移动端的开发挑战不亚于 PC 上对多个浏览器的支持,这一年,萌生了众多移动端框架,如 Sencha Touch/Zepto.js/JQ Mobile 等,相对 PC 端框架,它们更加轻便。

而移动端的崛起,带来了许多终端开发难题:多终端适配,多分辨率适配,远程调试等等,而随着这些难题一个个被解决,移动端生长的势头变得更加强盛。此时 Twitter 也推出了 Bootstrap, 这个前端开发工具包不仅方便了前端,也方便了后端同学,它的出现让快速建站更加简单。

编程**的切换,迎来了 CoffeeScript 和 TypeScript,这两个预处理语言的出现又为 JavaScript 引来了不少其他方向转型过来的开发者。JavaScript 的兄弟 Node.js,也在命令行领域开拓了一片不小的疆域,甚至有动摇 Perl 和 Ruby 地位的趋势。

在前端工程化上,几个派系相互争斗,产出了 AMD、CMD、UMD 等规范,也衍生了 SeaJS、RequireJS 等模块化工具。前端在这一年很有跳跃感。

13 年,爆发式增长,百花齐放

规范和标准上有不少产出。Web Components 的出现给前端开发开辟了新思路;WebDriver 规范的出来推动了自动化测试的进程,ECMAScript 6 的规范草案落地,Webapp 工作小组在这一年也是相当活跃。

Chrome 浏览器在这一年也有了很大的突破,开始支持 SPDY,使用 Blink 取代 webkit 作为 Chromium 的新渲染引擎,Chrome DevTools 的调试体验大幅度提升。这一年中,Chrome 连同其他浏览器厂商快速推动了各项草案规范的实现。

语言能力上依旧在增强,并且从 JS 开始扩散到 CSS,LESS、SASS 和 Stylus 等 CSS 预处理语言开始走俏,Web 开发变得更加紧凑。

而在无线端,应用不再局限于 Webapp,由于流畅度、性能等方面不能满足用户体验的需求,各大公司开始转向 Native 方向的研究,进而出现了 Hybrid 和 PhoneGap 的繁荣,它们为 JS 调用了提供更多的设备 API。

Node.js 大放异彩,很多公司在生产环境中使用 Node.js,同时也出现了诸如 Express、Meteor 等小巧的快速搭建 Node.js Server 的应用框架。

各浏览器的调试也是种类繁多、功能丰富,PhantomJS 在自动化测试上开始取代 Selenium,出现了众多的远程调试方案和工具。
前端工程化开始普及,各公司开始推出自己的前端集成开发解决方案。

14 年,移动端的崛起,HTML5 和 ES6 落地

HTML5 正式定稿,这意味着,web page 正式演变为 web application。ES6 华丽丽走进前端,走的很稳重,它的 Module/Class 等特性已经完全让这门语言具备了开发大型应用的能力。

大而厚的基础库难以满足灵活场景,Mobile 要求极致体验,MV* 库铺卷而来,如 vue/angular/knockout 等。

Web Components 跨终端组件快速发展,移动端开发迎来一次升华。Node.js 前后端分离的流行,中间层的出现改变了前后端的合作模式。2014 是颠覆式的一年,前端发展在这一年开始形成了一个短暂的稳定格局。

15 年,观念的转变,步入前端工业化生产

今年格外引人注目的框架是,类 React。Facebook 在 React.js Conf 2015 大会上推出了基于 JavaScript 的开源框架 React Native,它结合了 Web 应用和 Native 应用的优势,可以使用 JavaScript 来开发 iOS 和 Android 原生应用。在 JavaScript 中用 React 抽象操作系统原生的 UI 组件,代替 DOM 元素来渲染等。敲一次代码,能够运行在多个平台上,其优势可见一斑。除了 React ,还有手机淘宝推出的 Weex 框架,它吸收了 vue.js 的编程精华,编程风格更加简约。

在众多构建工具中,如今潇洒存活的并不多。体验完 grunt 和 browserify 后,gulp 顺势而至,尔后又出现了 webpack、jspm 等。而包管理工具,经历了 components、bower、spm 后,npm 开始主导整个市场。

Node.js 的应用已经铺天盖地,各大公司前端都把 Node.js 作为分离前后端的主要手段,并且在测试、监控等方面沉淀了大量内容。不过,这个市场是很苛刻的,Node.js 的性能难以达到 C/C++ 的水平,那么接下来要做的就是要提升性能,至少得接近 C/C++。

@法海 师兄 批注:对时间点的总结是,其实很多技术方案很早就出现了,只不过没有大规模应用,因此,对于上文中时间点的谬误,你可以将语句从「xxx 出现了」改成「xxx 得到广泛应用」。其实我发现,问题在于,一个技术领域的新起和发展并不是一年内能完成的,一个技术方案的出现和广泛应用也不是一年内能落地的,所以执着于以「年」为时间点来编史,会画地为牢。

Web 规范和标准

最开始,我们看到的 JavaScript 还只是一个简单的脚本语言,配合着 AJAX,在网页上翻腾了好几个年头。随着互联网趋势越来越明显,互联网业务量和业务复杂度不断增加,很多网页变得相当复杂,如让我们震惊了好一会儿的 Gmail,交互复杂,体验优良。为了更好的多人协作,代码中的 Utils 库越来越大,在这些库中,基础部分更多的是对 JavaScript 语言本身的拓展,比如给 String 加一个 repeat 函数,再加一个 trim 函数,再加一个 endWith 函数等等。

复杂的业务中会经常看到一层又一层的回调处理,回调的嵌套让代码的可读性变的很差,而且很难将多个异步并行处理。为了改变这种编程范式,我们做了很多的思考,使用事件监听,使用各种手段拉直回调,平坦地调用。

慢慢的,如果你在关注 W3C 小组的动向,会发现,那些被认可的,并且被广泛重复定义的东西,都被纳入了标准。最开始的 jQuery/prototype,前者主要是对浏览器做兼容处理,让开发者不再把精力放到浏览器的差异上;后者是对语言本身的拓展,对 JavaScript 各种类型做拓展,并且提供了一套拓展任何对象的功能集。而现在的开发,我们很大程度上不再依托这些类库。规范和标准已经把这些差异都统一了,String 中自带了 includes/startsWith/endsWith/repeat/padStart/padEnd 等函数,Array 自带了 from/forEach/of/keys/values/find/findIndex 函数…

规范的标准是为了让开发者得到更好的编程体验,编程不是目标,目标是将编程生产力转化成实际效益,越少的阻碍对开发者越有利。各浏览器厂商当然也认识到了这一点,他们不断地提升自己产品的体验,将标准中的新特性都融合进去,比如 ES6 中的 Promise/Generator/Class/Module 等等。在这些内容普及之前,我们不需要加入 jQuery/prototype 这些「不纯粹」的东西,而是添加两个 shim 和 polyfill,如 es5-shim,html5shiv 等等。待到山花烂漫时,再轻松删掉这些补丁程序。

这两年工程化很热,W3C 小组也看到了,这就是市场的需求,为了完成一个大型应用的编程,就必须模块化、组件化,于是在规范中也出现了 Module & Module Loader;Node.js 的到来,让很多前端工程师开始接触数据库操作,面对巨量的异步,我们忍气吞声写了无数的回调地狱,尽管使用了很多 Promise 相关的操作,程序结构依然松散难以阅读,于是规范中也开始出现了 async/await 等对 Generator 的上层封装。文字已经不能满足当代人的沟通需求,音视频等富媒体传输走进了我们的生活,于是规范中也出来了 WebRTC/WebAudio 等规范。

只要规范出来了,后续市面上就会根据规范来实现一套 shiv,这些 shiv 提供了同样的 API,提供了同样的编程体验。当浏览器自我进化完成之后,这些 shiv 也将成为历史,被开发者遗弃在代码的注释之中。这些都是规范和标准的魅力,它的存在,就是让开发者把精力投入到自己的业务之中,编程和范式的工作交给它。

在 这里 可以看到,W3C 各个小组最近都在干啥。标准不能囊括一切。

生态的自我完善和自我拓展

技术的更迭过于频繁,我们能够清晰地看到,很多人还在用更迭前一波甚至是前好几波的产品。

当年的 IE6,在战场上鏖战了 10 多个年头,依然屹立不到,而现在它在市面上依然有百分之一左右的占有率,这种小强精神不得不让人肃然起敬。“只要用户在,我们就得追随”,这可能是很多公司的服务理念,因为用户就是潜在的利润。正是因为这种服务理念,成就了 IE6 一个又一个的 5 年!然而低版本的 IE 已经不仅仅是被前端从业人员抵制和排斥了,网络安全、网络运维、QA 等等,各个技术岗位的人员都开始对他不屑,它的存在对工作效率、对安全、对很多方面产生了极为不良的影响,甚至影响到一些核心内容的推广,所以 2016 将是低版本 IE 消亡的一年,我也呼吁业界所有的朋友举起义旗反抗起来!

庆幸的是,也有人开始吃螃蟹了。从支付宝到天猫到淘宝,阿里巴巴在很多业务上已经主(bèi)动(bī)地放弃了对 IE6 和 IE7 的支持,甚至在统一接入层直接做了 302 跳转,提示用户更新浏览器或者引导流量到无线端。这是一个好的开始,我们期望这也是业界达成共识的开始!

HTTP 协议,从 1.0 快速过度到了 1.1,整个互联网的上层建筑变的十分稳固。当然,我也了解到依然有很多产品还是保持了 1.0 的状态,据说电信公司的很多产品就是使用 HTTP/1.0 进行通讯,这无疑让人惊愕。为了追求更高的效率,减少网络传输中的无效流量,W3C 工作组对 HTTP 协议也做了重新的定义,SPDY 就是 13 年比较火热的一个话题,Firefox 和 Chrome 都陆续开始支持 SPDY,后来在 SPDY 的基础上做了升级,正式定义为 HTTP/2.0,它的一个很大特点就是多路复用,这个小小的特点改变了我们前端编程的很多优化模式,比如

(1)域名不是越多越好,为了能够充分利用浏览器的连接数,我们给 JS 和 CSS 开一个域名,给 img 开好几个域名,网页打开的时候,恰到好处的利用浏览器的连接数上限限制。HTTP/2.0 的多路复用,就是可以在一个 HTTP 请求中进行多个资源的传输,如果域名散列,反而不能利用这个特性
(2)资源合并没有任何优势,以前的资源合并是为了减少请求数以节约建立 TCP 链接的网络开销和头部传输的流量开销,而在 HTTP/2.0 中,一个 HTTP 请求上完全可以把所有的资源全部推送过来,如果合并了资源,反而不能良好运用浏览器对资源的缓存。

当然,除了多路复用,还有很多其他的优化,比如传输的数据为二进制流,HEAD 头会被压缩处理,服务器可以向客户端推送内容等。在这个技术水平指数式增长的年代,我相信以后的革新不会比消灭 IE6 痛苦。

模块加载上,经过了各派系的争论之后,流传下来几个不错的产品 SeaJS、RequireJS 等,那么那个模块加载器将成为工具平台中短暂的终点呢?似乎这些都不是。当我们按照规范中的方式进行模块定义,按照规范中的方式加载定义的模块时,加载这个流程就显得不那么重要了,因为这些事情最后都会变成 shiv/polyfill 的事情,最终会变成浏览器的固有属性。

当一个东西在社区中被暴力追捧的时候,会有很多衍生的产品出来,当这些衍生物根深蒂固时,可能又会出现一个更加原生更加符合开发习惯的东西出来。就像 jQuery,我们为它编写的插件不计其数,而在工程化的需求冲击下,它却显得那么的弱不禁风,因为它关注的点和当前的发展态势不太吻合,仅此而已。

Mobile 的发展驱动着战场的转移

记得当年拿着 Nokia5230 学完了 HTML 和 JavaScript 的入门,那屏幕尺寸也就是三个手指的宽度,紧紧攥在手里看着页面混排效果极差的网页文档。

现如今,iPhone 都出到 6s 了,一个版本一个尺寸,而且尺寸越来越大,还有各种宽高不一的 Android 机器,种类繁多。以前的触屏是电阻式,只支持单点触碰;而现在电容式的触屏精度更高,还支持多指触控,这如丝般顺滑的体验在三四年前是完全体会不到的。曾经手机开一个程序久了就会卡,动不动还会自动重启;而现在的手机开一堆程序,完全无感知,这就是硬件发展前后的差异。

手机已经成为了人们生活中不可或缺的一部分,甚至成为了一些人身体的一部分,淘宝今年双十一的数据显示,国内移动端的消费比例已经远远超过了 PC 端,占比 68%。面对庞大的用户,我们的技术是否做好了充足的准备,这里还得打一个问号。

PC 上那一套经验不是直接搬到移动端就可以使用了,在移动端还需要解决更多的问题:

(1)多分辨率问题,这里涉及到了响应式设计和前端响应式技术
(2)不同网络环境的网页加载优化问题,2g/3g/4g/wifi
(3)手指交互带来的一系列体验问题
(4)为了提升用户体验,将 Web Native 化 —— 类 React 技术带来的一系列问题
(5)远程调试问题
(6)移动安全问题等等

上面提到的问题很多已经有了优秀的解决方案,当然也有很多未提及的。WebApp 的性能、流畅度和稳定性远远不如原生应用,同时它也无法良好地运用设备提供的原生功能,这些都是大家转投 Native 的原因。

端的融合

不同分辨率的手机,不同物理尺寸的终端,为了保持良好的视觉体验和用户体验,我们不得不为每一个尺寸写一份 Media Query 代码,那么对应的,设计师也需要设计多套版式供前端使用,这给设计师、前端和测试带来了无尽的麻烦。为此,我们通过前端技术重塑屏幕,重新定义像素尺寸,使用流式布局,通过百分比来响应不同的终端尺寸。这是端的融合。

后续的 Mobile 的技术发展方向上,应该是相当明确的。很多公司都是三套人马维护三端的程序,iOS、Android 和 Web,而这三端做的事情都是一样的,一样的界面,一样的后端接口,一样的交互方式。为了能够快速响应业务的变更,我们不得不将三端合并为一端对待,用一套程序编程成三端代码,然后发布到三个平台上。这也是端的融合。React 系列技术发展到此,绝对不是终点,它只是一个探路灯,给我们照明了方向。

技术需要为业务做保障,而好的技术是能够及时响应业务的变化,我们不可能投入大量的人力在 Web 的修补工作上,通过开发统一工具,屏蔽端和端之间的差异,统一开发模式和开发体验,这才是 Mobile 的未来。

当然,回到我们之前说的规范和标准,我们目前所做的「屏蔽差异」工作,今后,也会有统一的标准来规范,目前手机厂商没有这个共识,是因为还处于当年 Chrome、Firefox 抢占 IE6 市场份额的阶段。端的最终融合在于一个统一的标准,以及强有力的执行。

栈的融合

我刚接触前端的时候,还没有听说「全栈」,Web 技术栈往小里说,包含了从前端设计、交互、前端实现、网络数据传输、后端实现、后端运维和数据库等几个方面,能短时间内从无到有实现这么一套系统,并且能够抗得住一定流量冲击的人,我们可以称之为全栈工程师。能够有架构有条理地实现这套系统,并且抗得住大流量、有集成测试、有监控的,这种我们可以称之为资深全栈工程师。现在不乏这种人才,也不乏自吹为这种人。

栈的融合得益于 Node.js 的出现,作为前后端分离的桥梁,它拉近了前端工程师与后端的距离,有的人在这座桥梁上卖力行走,渐渐的也从前端走进 了后端,甚至走进了后端的运维。至此,前端也拥有了部署和发布整个应用的能力,这是一个质的突破。

使用 Node.js,简单几行程序便能实现一个 web 服务器、便能搭建一个多人聊天的网页,它的便捷性可见一斑。NPM 社区的发展,沉淀了成千上万的组件包,一行命令即可获取,这种组件拼凑式的开发,任何功能的实现都不会显得太复杂,而这里的「不复杂」也蕴含了无数的坑坑洼洼,在这一层的融合上也会遇上不少阻碍:

(1)冗余的庞大的包内容,为了使用一个小功能,我们从网络上拉取下来一个巨大的包,而且这里的「巨大」对很多人来说都是无感知的,很少会有人进入 node_modules 去查看依赖的第三方包是如何实现的,实际情况可能会相当震撼,第三方包还引用了一堆第三方包,这些包都会在 Node.js 执行的时候被收纳进去,放在内存中。
(2)猛烈的迭代,今年的 Node.js 被人嫌弃迭代太慢了(当然,这是表面原因),走出了一个分支 io.js,发展了一会儿,进度赶超了 Node.js,后来觉得一家人不干两家活,又合并回去了。虽说上层 API 几乎没有变化,但是底层却被翻了一个天。
(3)偶尔的巨大漏洞,每隔一端时间就会暴露 Node.js 存在漏洞,这些漏洞的补救措施就是立即升级版本号,比较让人担心受怕。
(4)后端意识不强烈,前端占领了中间层的开发,有的时候还干这后端的活儿,然而却没有后端沉淀多年固有的意识,测试和监控做的相当潦草。

JavaScript 从客户端的脚本语言纵身跃进进入了后端行列,而今也开始深入到移动端 Native 领域,确实是无孔不入,这可能就是语言的特性,也可能是技术本身就在寻求融合点,把有差异的地方全部躺平,然后用统一的方式去关注业务,关注用户。端和栈也在融合。

后端服务化,云数据,云安全

用户体验变得越来越重要,响应式技术的发展也是后续网页应用的一大特点,端和端之间的差异只是在表现上,数据这一层差异不是特别大,很多应用 PC 和 Mobile 共用一套接口,或者 Mobile 的接口在 PC 接口的基础上做了一层包装,对接口字段做了些许删减。后端为了响应各个端之间的数据需求,也需要关注数据的可利用性,接口包装的拓展性等,这是后端服务化的一个表现。移动端的开发上,前后端间隙十分明显,越来越多移动端应用的发布已经脱离了后端,前端完全通过异步方式获取数据。

业务变化很快很快快,今天这个产品被并购,明天那个业务被砍掉,每个人负责的业务线可能冷不丁地就变了。很多大公司的决策是由上往下的,上面微动,下面可能就是大动,可能某个部门就不存在了,也可能被划分成几个产品部门。

所以「大后台,小前台」的趋势必然形成。前端,毫无疑问,在这个前台之中。前台的特点是灵活的,多变的,可快速重组的。对后台而言,为了响应前台的变化,需要提供更细粒化的 API,将数据打散,打得更加零碎,零碎的数据易于重组,这是在考验后端的架构能力。如今,很多前端也都是半栈工程师,盘踞在前后端中间层上,然而如何迎接这种后端服务化的模式,似乎这个准备还是不够充足的。

GraphQL 的出现场景跟 React 类似,React 是前端应对不同场景的一种强有力手段,而 GraphQL 则是后端应对不同需求场景的一次尝试,Web APIs 将会成为 Web App 和 Mobile App 的一个中心点,前端基于后端的 RESTful 服务构建应用,这里面存在太多未知的问题需要探索,这是一个大数据下探索的新起点,也给前端开发者创造了无数的可能。

这几年各类网盘,各个云服务商都在抢占市场,有提供图片储存的,有提供 CDN 静态资源缓存的,有提供大文件储存的,也有卖数据库服务的。种类繁多,而归根到底都是,你付钱给我,我提供储存和安全,还提供方便的 SDK 让你获取自己的数据。云服务卖的是一套服务,它是把所有人的数据风险集于一身,用强硬的技术做安全防御。云,赋予了我们无穷的想象空间。

三辆马车,我们还差一辆

开发功能对很多人来说是轻松活儿,基本的前端语言加些复杂的特效,实现成本不会很高;即便是搭建一个网站,使用 Node.js 社区中的框架也能够轻松实现。然后极少人会去关注每个功能点的测试,一个项目下来基本看不到测试用例,更不用说会去做监控相关的事情。结果就是,踏过了无数的坑洼之后终于上线了,而后续加功能的时候发现,加了东西就跑不通,新内容影响了之前的逻辑,只好去修复之前的逻辑,修好之后发现更早之前的逻辑又不通了,整个修复过程就像玩多米诺骨牌。

程序开发三板斧:功能、测试和监控。在 github 上可以看到很多程序都加入了持续集成,这是一个好兆头,意味着我们写的程序也越来越健壮,至少贡献给世人使用的程序是健壮的。很多程序的代码覆盖率也达到了 90%+,这些数据都是重视测试的证据。

然而,三辆马车,我们最后一辆依然没有开动起来。很多公司都会有自己的 log 平台,每个用户访问页面中的任何一个链接都会将用户信息和访问信息以 log 日志形式收集到 log 平台上,然后通过监控平台或者离线分析的方式,获取业务数据或者技术数据,进行分析和二次开发。这些东西在大公司见的很多,而这方面的东西在前端,尤其是使用 Node.js 做程序开发的前端身上,看到的并不多。

最后

2016 年,我觉得技术上的新创造会稍微缓和些,这两年很多人已经被新技术冲击得有些找不着方向了,同一类东西,前者还没学完,后者就开始火爆了,紧接着又是一阵技术的凋零和新技术的出现,这样搞久了也会有一丝的疲倦。而更多的会关注,如何更好地服务多端,如何更大幅度地提升开发体验和用户体验,很多技术都会往性能、往极致这个方向上钻研。

写长文真不轻松。写到这里,感觉说的不通透,还有很多想说的,但是个人理解力有限,也难以表达全面。技术的变化很快,今天说过的东西,到了明天就可能过时了。我们猜不透未来,只能把现有的东西好好消化吸收下,留下一个话柄,给读者吧。

[原发布时间: 2016-03-28] HTML5的PostMessage学习

HTML5提出了一个新的用来跨域传值的方法,即postMessage(这个名字太通俗了所以你最好看看是不是自己写过一个同名的把它覆盖了)。幸运的是IE8就开始支持了。

我们假设有两个网站,1.com与2.com,我在1.com的页面上通过iframe或window.open或超链接打开了一个2.com的网页,此时我要在2.com上做操作的时候,给1.com传值,让1.com有所变化。这个过程就是个跨域的过程。
如果你对window.open熟,你就会知道通过window.open打开的网页(我们称之为子网页),可以通过window.opener对象,访问到把它打开的页面(父网页),这样一来,调用父页面的函数就是非常简单的事了。但是,在跨域的条件下,window.opener就成了一个空对象,“没有权限”,浏览器会这么告诉你。
比如,你的父页面有个函数叫callback,然后你子页面本可以这样调用:window.opener.callback(),同域时能成功,跨域时就没有权限了。
但是,此时你调用window.opener.postMessage(),却可以成功!
关于跨域传值的痛苦我就不多说了,本文只说一些前两天学习postMessage时了解到的重要知识点。

postMessage语法

window.postMessage(msg,targetOrigin)

这里我要专门说一下postMessage要通过window对象调用!因为这里的window不只是当前window,大部分使用postMessage的时候,都不是本页面的window,而是其他网页的window!如:
1,iframe的contentWindow
2,通过window.open方法打开的新窗口的window
3,window.opener
如果你使用postMessage时没有带window,那么,当然,你就是用的本页面的window来调用了它。
参数说明

msg

这就是要传递的消息了。它可以是一切javascript参数,如字符串,数字,对象,数组,而不是和json一样只局限于字符串,很强大吧?

targetOrigin

这个参数称作“目标域”,注意啦,是目标域不是本域!比如,你想在2.com的网页上往1.com网页上传消息,那么这个参数就是“http://1.com/”,而不是2.com.
另外,一个完整的域包括:
协议,主机名,端口号。如:http://g.cn:80/
获取postMessage传过来的消息
要对postMessage传来的消息进行处理,就要在页面上加一个onmessage事件。如:

window.addEventListener('message',function(e) {
    console.log(e.origin,e.data);
    alert('有数据传来了!');
})

要注意:最好是通过addEventListener或attachEvent来加入onmessage事件,而不要直接window.onmessage=function(){},因为有的浏览器这样加会识别不了(如低版Firefox)
这个onmessage事件接受一个参数,就是代码里的e,实际上他就是一个event对象。但他里面有很明显的3个参数与其他event对象不一样,即:
1,data:顾名思义,是传递来的message
2,source:发送消息的窗口对象
3,origin:发送消息窗口的源(协议+主机+端口号).比如从2.com往1.com发了消息,那么1.com收到消息时,e.origin就是2.com
最重要的就是data了,你可以用e.data取得他,然后做后续操作了。不过为了安全,你最好先判断一下e.source和e.origin是不是正确来源,再作操作。

完整的postMessage流程示例

接着刚才的例子来,我着重讲一个弹窗给父页面传消息的例子。
我们的父页面叫1.com,他上面有关键代码是:

window.addEventListener('message',function(e) {
    console.log(e.origin,e.data);
    alert('子页面有数据传来了!');
})

就这么简单。而弹出窗口(2.com)上的代码是:

var domain='http://1.com/';
window.opener.postMessage({obj:'I am a obj'}, domain)

还是很简单吧!你看,跨域时本来不能访问的window.opener可以访问了——不过你直接调用父页面的方法还是会失败!就是这么不讲理。
其他应用场景的例子
1,必须要说明:通过超链接打开的新窗口也能用window.opener来访问其父页面,代码跟上面一样
2,iframe的例子
父页面:

varo=document.getElementsByTagName('iframe')[0];
o.contentWindow.postMessage('Hello World',"*");
//向框架页传消息

被框架包裹的子页面:

window.addEventListener('onmessage',function(e) {
    if (e.domain=='1.com') {
        if (e.data=='Hello World') {
            e.source.postMessage('Hello',"*");
            //反过来向父页面传消息
        } else {
            alert(e.data);
        }
    }
});

这个例子充分说明了postMessage是双向的。
3,window.open一个窗口,然后向他传消息
父页面:

var domain2='http://2.com/';
var win=window.open(domain2+'Portal/2.com.html','wwwwwwww')
setTimeout(function(){
    win.postMessage('ddddddddd',domain2
)},2000)

子页面:

window.addEventListener('message',function(e){
    console.log(e.origin,e.data)
})

要注意父页面中的setTimeout,也就是要延迟传消息,因为子页面不可能瞬间加载完成,他的onmessage事件也就没初始化成功,这时给他传消息,当然是收不到的了。

后记

1,IE8+虽然支持postMessage,但只支持iframe的方式,window.open打开的新窗口之间,没法用。直到IE10才有相关改进
2,如何在本地模拟跨域呢?在hosts文件里加入:127.0.0.1 1.com127.0.0.1 2.com 就可以模拟出2个不同的域名了。

[原发布时间: 2016-02-26] 常见的HTTP状态码

笔试必考题之一,但没有什么技术含量,你只需要把常见的记下来即可。

1** (消息)

这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。由于 HTTP/1.0 协议中没有定义任何 1xx 状态码,所以除非在某些试验条件下,服务器禁止向此类客户端发送 1xx 响应。

100: 服务器仅接收到部分请求
101: 服务器已经理解了客户端的请求,并将通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求。

2** (请求成功)

这一类型的状态码,代表请求已成功被服务器接收、理解、并接受

200: 请求成功(其后是对GET和POST请求的应答文档。)
201: 请求被创建完成,同时新的资源被创建。

3** (重定向)

这类状态码代表需要客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的 Location 域中指明。

300: 多重选择。链接列表。用户可以选择某链接到达目的地。
301: 页面永久重定向
302: 页面临时重定向
304: 资源未被修改,服务器告诉客户,原来缓冲的文档还可以继续使用。

4** (客户端错误)

这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理。除非响应的是一个 HEAD 请求,否则服务器就应该返回一个解释当前错误状况的实体,以及这是临时的还是永久性的状况。这些状态码适用于任何请求方法。浏览器应当向用户显示任何包含在此类错误响应中的实体内容。

400: 服务器未能理解请求
401: 被请求的页面需要用户名和密码。
403: 对请求页面的访问被禁止。(通常为没有读权限)
404: 服务器无法找到被请求的页面。
408: 超出服务器等待时间
413: 由于所请求的实体的太大,服务器不会接受请求。
414: 由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。

5** (服务器错误)

这类状态码代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。除非这是一个HEAD 请求,否则服务器应当包含一个解释当前错误状态以及这个状况是临时的还是永久的解释信息实体。浏览器应当向用户展示任何在当前响应中被包含的实体。

500: 请求未完成。服务器遇到不可预知的情况。
502: 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
503: 服务器临时过载或当机。
504: 网关超时。

[原发布时间: 2016-02-19] HTML5摇一摇效果

仿微信摇一摇

2015年的春节,微信借着春晚通过摇一摇抢红包,再一次的走近大家的眼中,创出一个全名抢红包的事情,不知道大家是否都抢到红包了没,别急,让我们自己写一个页面来再一次的过一把瘾吧。

前言

所谓抢红包,其实就是微信的摇一摇,不得不说,这个摇一摇的动作在其他的应用里面真的是很少被使用,那么我们如何通过js来实现呢?
在html5中,有个属性可以来获取设备的运动传感器的时间、状态、加速度等数据,常见的数据就是来自于设备的陀螺仪、加速计、罗盘。
其中,
deviceorientation事件,提供了设备的物理方向信息;
devicemotion事件,提供了设备的加速度。
很明显,通过这两个事件,我们能做摇一摇、重力感应、指南针等应用。

下面让我们开始制作摇一摇的旅程吧。

第一步,首先来判断一下,当前这个设备是否支持运动传感事件。

if(window.DeviceMotionEvent){//判断设备是否支持运动传感事件。
    window.addEventListener('devicemotion', shake, false);//如果支持,那么就绑定shake方法到事件上
}else{
    alert('本设备不支持摇一摇功能’);//如果不支持,提示即可
}

第二步,编写shake方法。

首先让我们分析一下,用户什么样子的操作才能算作使用摇一摇了呢?

  1. 用户摇动手机,是以一个方向为主的摇动。
  2. 用户摇动手机的时候,加速度肯定是有变化的。
  3. 设置一个阈值,判断用户单位时间内的运动状态,以避免将用户的正常行为当作触发摇一摇。
//首先定义一下,全局变量
var lastTime = 0;//此变量用来记录上次摇动的时间
var x = y = z = lastX = lastY = lastZ = 0;//此组变量分别记录对应x、y、z三轴的数值和上次的数值
var shakeSpeed = 800;//设置阈值

//编写摇一摇方法
function shake(){
    var acceleration = eventDate.accelerationIncludingGravity;//获取设备加速度信息
    var nowTime = new Date().getTime();//记录当前时间

    //如果这次摇的时间距离上次摇的时间有一定间隔 才执行
    if(nowTime - lastTime > 100){
        var diffTime = nowTime - lastTime;//记录时间段
        lastTime = nowTime;//记录本次摇动时间,为下次计算摇动时间做准备
        x = acceleration.x;//获取x轴数值,x轴为垂直于北轴,向东为正
        y = acceleration.y;//获取y轴数值,y轴向正北为正
        z = acceleration.z;//获取z轴数值,z轴垂直于地面,向上为正
        //计算 公式的意思是 单位时间内运动的路程,即为我们想要的速度
        var speed = Math.abs(x + y + z - lastX - lastY - lastZ) / diffTime * 10000;
        if(speed > shakeSpeed){//如果计算出来的速度超过了阈值,那么就算作用户成功摇一摇
                //这里就是放置如果用户成功的摇一摇,将要触发的事件,例如提示摇到了谁,摇到了多少金币等等
        }
        lastX = x;//赋值,为下一次计算做准备
        lastY = y;//赋值,为下一次计算做准备
        lastZ = z;//赋值,为下一次计算做准备
    }
}

好了,核心的东西我们已经写完了,剩下的其实就是一些页面上的动画效果,当摇一摇被触发才执行的事件,这就要和你写的项目相关联了,这里就不一一写了。

附上本次实例地址:http://shake.coolfishstudio.com

[原发布时间: 2016-03-07] Safari无痕浏览影响localStorage

用localStorage也已经很久了,这次发现localStorage在iPad/iPhone的Safari的无痕浏览模式中存在一个问题。

在无痕浏览中使用localStorage.setItem()居然会报错,但在window对象下确实有localStorage.setItem这个方法。
在iPad/iPhone中用Chrome的隐身模式是可以用localStorage.setItem()。
Safari的无痕浏览这么严格,用了localStorage.setItem()居然还会报错。
既然无痕浏览不能使用localStorage.setItem(),但也不能让它影响我们的代码执行,最后只能给一个提示,告诉用户无痕浏览无法保存。

try { 
    localStorage.setItem(key, d); 
} catch (e) { 
    alert("您处于无痕浏览,无法为您保存"); 

[原发布时间: 2016-04-06] HTML调用PC摄像头

使用HTML5中的canvas和video技术实现调用PC摄像头

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HTML5调用电脑摄像头实例</title>
    <script type="text/javascript">   
        window.addEventListener("DOMContentLoaded", function() {  
            // Grab elements, create settings, etc.  
            var canvas = document.getElementById("canvas"),  
                context = canvas.getContext("2d"),  
                video = document.getElementById("video"),  
                videoObj = { "video": true },  
                errBack = function(error) {  
                    console.log("Video capture error: ", error.code);   
                };  
           
            // Put video listeners into place  
            if(navigator.getUserMedia) { // Standard  
                //alert("支持navigator.getUserMedia");
                navigator.getUserMedia(videoObj, function(stream) {  
                    video.src = stream;  
                    video.play();  
                }, errBack);  
            } else if(navigator.webkitGetUserMedia) { // WebKit-prefixed  
                //alert("支持navigator.webkitGetUserMedia");
                navigator.webkitGetUserMedia(videoObj, function(stream){  
                    video.src = window.webkitURL.createObjectURL(stream);  
                    video.play();  
                }, errBack);  
            }  
            else if(navigator.mozGetUserMedia) { // Firefox-prefixed  
                //alert("支持navigator.mozGetUserMedia");
                navigator.mozGetUserMedia(videoObj, function(stream){  
                    video.src = window.URL.createObjectURL(stream);  
                    video.play();  
                }, errBack);  
            }  
            // 触发拍照动作  
            document.getElementById("snap").addEventListener("click", function() {  
                context.drawImage(video, 0, 0, 640, 480);  
            }); 
 
        }, false);   
    </script>
</head>
<body>
    <video id="video" width="640" height="480" autoplay></video><br>
    <button id="snap" >点击拍照</button>  <br>
    <canvas id="canvas" width="640" height="480"></canvas>  
</body>
</html>

[原发布时间: 2016-03-06] Sublime常用快捷键

alt+shift+2 将sublime Text拆成左右两块
alt+shift+4则拆成从左到右四块
alt+shift+8则拆成上下两块
alt+shift+9则拆成上下三块
Ctrl+Shift+P:打开命令面板
Ctrl+P:搜索项目中的文件
Ctrl+G:跳转到第几行
Ctrl+W:关闭当前打开文件
Ctrl+Shift+W:关闭所有打开文件
Ctrl+Shift+V:粘贴并格式化
Ctrl+D:选择单词,重复可增加选择下一个相同的单词
Ctrl+L:选择行,重复可依次增加选择下一行
Ctrl+Shift+L:选择多行
Ctrl+Shift+Enter:在当前行前插入新行
Ctrl+X:删除当前行
Ctrl+M:跳转到对应括号
Ctrl+U:软撤销,撤销光标位置
Ctrl+J:选择标签内容
Ctrl+F:查找内容
Ctrl+Shift+F:查找并替换
Ctrl+H:替换
Ctrl+R:前往 method
Ctrl+N:新建窗口
Ctrl+K+B:开关侧栏
Ctrl+Shift+M:选中当前括号内容,重复可选着括号本身
Ctrl+F2:设置/删除标记
Ctrl+/:注释当前行
Ctrl+Shift+/:当前位置插入注释
Ctrl+Alt+/:块注释,并Focus到首行,写注释说明用的
Ctrl+Shift+A:选择当前标签前后,修改标签用的
F11:全屏
Shift+F11:全屏免打扰模式,只编辑当前文件
Alt+F3:选择所有相同的词
Alt+.:闭合标签
Alt+Shift+数字:分屏显示
Alt+数字:切换打开第N个文件
Shift+右键拖动:光标多不,用来更改或插入列内容
鼠标的前进后退键可切换Tab文件
按Ctrl,依次点击或选取,可需要编辑的多个位置
按Ctrl+Shift+上下键,可替换行

[原发布时间: 2016-03-09] CSS中常用的几种居中方法

听了小伙伴问到css居中的方法, 今天我们就总结几种方法:

1,使用position:absolute,设置left、top、margin-left、margin-top的属性

.one{
            position:absolute;
            width:200px;
            height:200px;
            top:50%;
            left:50%;
            margin-top:-100px;
            margin-left:-100px;
            background:red; 
}

这种方法基本浏览器都能够兼容,不足之处就是需要固定宽高。

2,使用position:fixed,同样设置left、top、margin-left、margin-top的属性

.two{
              position:fixed;
              width:180px;
              height:180px;
              top:50%;
              left:50%;
              margin-top:-90px;
              margin-left:-90px;
              background:orange;
}

大家都知道的position:fixed,IE是不支持这个属性的

3,利用position:fixed属性,margin:auto这个必须不要忘记了。

.three{
             position:fixed;
             width:160px;
             height:160px;
             top:0;
             right:0;
             bottom:0;
             left:0;
             margin:auto;
             background:pink;
}

4,利用position:absolute属性,设置top/bottom/right/left

.four{
            position:absolute;
            width:140px;
            height:140px;
            top:0;
            right:0;
            bottom:0;
            left:0;
            margin:auto;
            background:black;
}

5,利用display:table-cell属性使内容垂直居中

.five{
             display:table-cell;
             vertical-align:middle;
             text-align:center;
             width:120px;
             height:120px;
             background:purple;
}

6,最简单的一种使行内元素居中的方法,使用line-height属性

.six{
             width:100px;
             height:100px;
             line-height:100px;
             text-align:center;
             background:gray;
}

这种方法也很实用,比如使文字垂直居中对齐

7,使用css3的display:-webkit-box属性,再设置-webkit-box-pack:center/-webkit-box-align:center

.seven{
             width:90px;
             height:90px;
             display:-webkit-box;
             -webkit-box-pack:center;
             -webkit-box-align:center;
             background:yellow;
             color:black;
}

8,使用css3的新属性transform:translate(x,y)属性

.eight{
             position:absolute;
             width:80px;
             height:80px;
             top:50%;
             left:50%;
             transform:translate(-50%,-50%);
             -webkit-transform:translate(-50%,-50%);
             -moz-transform:translate(-50%,-50%);
             -ms-transform:translate(-50%,-50%);
             background:green;
}

这个方法可以不需要设定固定的宽高,在移动端用的会比较多,在移动端css3兼容的比较好

9、最高大上的一种,使用:before元素

.nine{
            position:fixed;
            display:block;
            top:0;
            right:0;
            bottom:0;
            left:0;
            text-align:center;
            background:rgba(0,0,0,.5);
}
.nine:before{
            content:'';
            display:inline-block;
            vertical-align:middle;
            height:100%;
}
.nine .content{
            display:inline-block;
            vertical-align:middle;
            width:60px;
            height:60px;
            line-height:60px;
            color:red;
            background:yellow;
}

[原发布时间: 2016-04-09] 移动端web的head通用写法

<head lang="en">
    <meta charset="UTF-8">
    <!-- 优先使用 IE 最新版本和 Chrome -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
    <!-- 为移动设备添加 viewport -->
    <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <!-- 添加到主屏后的标题(iOS 6 新增) -->
    <meta name="apple-mobile-web-app-title" content="">
    <!-- 是否启用 WebApp 全屏模式,删除苹果默认的工具栏和菜单栏 -->
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <!-- 设置苹果工具栏颜色 -->
    <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
    <!-- 添加智能 App 广告条 Smart App Banner(iOS 6+ Safari) -->
    <meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL">
    <!-- 忽略页面中的数字识别为电话,忽略email识别 -->
    <meta name="format-detection" content="telphone=no, email=no"/>
    <!--下面三个是清除缓存 微信浏览器缓存严重又无刷新;这个方法调试的时候很方便-->
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <title></title>
</head>

[原发布时间: 2016-04-11] 一个括号引发的撕逼

前几天在网上看到很有趣的两个问题:
{}+{} 等于多少?
({}+{}) 等于多少?

本人一看,这么小儿科的问题,都让开,让我来装下逼,于是答到:
{}+{} 等于 NaN
({}+{}) 等于 NaN
答完,别人却说不对。我擦,打死我,也不信,于是我在浏览器试了一下,发现结果还真的是不对的。
{}+{} 等于 NaN
({}+{}) 等于 "[object Object][object Object]"
装逼不成,反被撕。这下老脸都不知道丢到哪里去了。冷静一番后,我对这个问题产生了深厚的兴趣,为什么加了个括号后,结果却差别这么大。
经过一番苦苦找寻源由后,我终于发现原来是浏览器解析的问题。
在{ } + { }中,

  1. 浏览器会把第一个{ }当成是一个语句块,像if语句中的{}一样。因为当浏览器寻找一份声明中,看到第一个左括号时,即{,就傻乎乎把它当做是一个语句块,但是里面的内容是空的,所以什么也不会做。
  2. 而接下来遇到+时,浏览器会把它当成是一元运算符,所以+{}会被当成表达式。在表达式中,{是对象初始化,而不是一个语句块开始,所以{}是一个对象,然后+试图转化{}对象成为一个数字,最终得到NaN。
    所以 {}+{} 其实等价于 +{}
    在({}+{})中,
  3. 当浏览器遇到(,会把它当成是一个运算符,所以({}+{})会被当成一个一个表达式。
  4. 在表达式中,两个{}会被当成两个对象,而一元运算符+,则变成字符串连接符,+将尝试将两个对象转化为字符串,所以两个{}分别调用自己的toString方法,将自己转化为"[object Object]" 。
    所以最终的结果是 "[object Object]" +"[object Object]" 等于 "[object Object][object Object]"

说到实际运用中,
我们以前一般会使用eval函数格式化JSON数据,但是我们会在参数中是添加'('和')',例如eval("({'a':1,'b':2})")。
聪明的*年啊,现在你知道原因是什么了吧!

[原发布时间: 2016-03-10] CSS中的伪类和伪元素

1.CSS3为了区别伪类和伪元素,明确使用单冒号来表示伪类,双冒号来表示伪元素。但为兼容性考虑,目前基本还是使用单冒号来表示。
2.搜索引擎不会搜索伪元素的信息。因此,不要通过伪元素添加你想让搜索引擎索引的重要内容

伪类

伪类与类相似,但又没有类附加标签上。伪类分为UI伪类和结构化伪类。

UI伪类

:link(将样式添加到未被访问的链接上)

:visted(将样式已添加到访问的链接上)

:hover(将样式添加到鼠标悬浮的元素上)

:active(将样式添加到被激活的元素上)

:focus(将样式添加到被选中的元素上)

结构化伪类

:first-child(将样式添加到第一个子元素上)

:last-child(将样式添加到最后一个子元素上)

伪元素

伪元素是在文档中若有实无的元素。

主要有以下几种

:first-letter(将样式添加到第一个字母)

:first-line(将样式添加到第一行)

:before(在某些元素前面插入某些内容)

:after(在某些元素后面插入某些内容)

看到:after,大家脑子里应该都能浮现出那个清除浮动的CSS的吧。没错,就是这个。

.clearfix:after {
    content:".";
    display:block;
    height:0;
    visibility:hidden;
    clear:both;
}

区别

仔细琢磨下它们的定义。
伪类的实现就好比给这个标签添加了一个虚拟的类。

举个例子:

.hover{
    font-size:20px;
    color:red
}
<a href="#" class="hover">Hello,World</a>

这么一对比,”伪类“就顾名思义了啊。

而伪元素则好比添加了一个新的标签。

p:first-letter{
    font-size:20px;
    color:red
}
<p>Hello,World</p>

若不用伪元素,实现同样的效果,需要这么做

.first-letter{
    font-size:20px;
    color:red
}
<p><span class="first-letter">Hello,World</span></p>

因此总结下区分的方法:现实相同效果是需要添加一个类还是一个元素标签。

[原发布时间: 2016-03-26] html5移动端引入优酷视频iframe自适应

重点是 使得 iframe 的宽高比为 9:16 就好

1、要引入的视频

<iframe height=498 width=510 src="http://player.youku.com/embed/XMTI4MjU5OTA3Mg==" frameborder=0 allowfullscreen></iframe>

2、css里设置iframe的宽度为100%

3、根据屏幕宽度自适应,这里我设定视频16/9的固定比例

window.onload = window.onresize = function () { resizeIframe(); } 
var resizeIframe = function () { 
    var bodyw=document.body.clientWidth; 
    for (var ilength=0;ilength<=document.getElementsByTagName("iframe").length;ilength++) { 
        document.getElementsByTagName("iframe")[ilength].height = bodyw*9/16;//设定高度 
    }
}

优酷视频

[原发布时间: 2016-03-15] Mobile Web Retina 下 1px 边框解决方案

1px的边框在devicePixelRatio = 2的retina屏下会显示成2px,在iphone 6 plug 下,更显示成3px。由其影响美感。
还好,时代总是进步的。也许很多人都不知道, 现在IOS8下,已经支持0.5px了.. 那么意味着,在devicePixelRatio = 2下,我们可以使用如下的css代码:

div {
    border: 1px solid black;
}
@media (-webkit-min-device-pixel-ratio: 2) {
    div {
        border-width: 0.5px;
    }
}

但是在ios7以下,android等其他系统里,0.5px会被显示为0px,即该解决方案需要写hack兼容老旧系统。

三种方案:

1、JS判断UA

JS判断UA,是否是ios8+,是的话则输出类名hairlines,为了防止重绘,这段代码加在head里即可。

if (/iP(hone|od|ad)/.test(navigator.userAgent)) {
    var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/),
        version = parseInt(v[1], 10);
    if(version >= 8){
        document.documentElement.classList.add('hairlines')
    }
}

2、JS判断是否支持0.5px边框

JS判断是否支持0.5px边框,是的话,则输出类名hairlines。

if (window.devicePixelRatio && devicePixelRatio >= 2) {
    var testElem = document.createElement('div');
    testElem.style.border = '.5px solid transparent';
    document.body.appendChild(testElem);
    if (testElem.offsetHeight == 1)
    {
    document.querySelector('html').classList.add('hairlines');
    }
    document.body.removeChild(testElem);
}
// This assumes this script runs in <body>, if it runs in <head> wrap it in $(document).ready(function() {   })

相比于第一种方法,这种方法的可靠性更高一些,但是需要把js放在body标签内,相对来说会有一些重绘,个人建议是用第一种方法。

3、服务端做ios版本判断

服务端做ios版本判断,输出相应的类名

相比于JS的实现,个人更倾向于在服务端完成,这样前端也少几行代码,并且更加可靠。

如在wormhole里的实现(wormhole是nodejs环境下的一个服务端渲染模版的容器)

{{#if($plugins.detector.os.name === "ios" && $plugins.detector.os.version >= 8)}}
    {{set (hairlines = "hairlines")}}
{{/if}}
<html class="{{hairlines}}">

加上类名后,就可以针对该类名写相应的css了。比如:

div{border:1px solid #000}
.hairlines div{border-width:0.5px}

也许你会问,那ios7以下和其他android机下怎么搞?我的建议是:还是维持老样,不去处理,随着时间的推移,我相信最终都会支持0.5 和 0.3 px边框的。

如果硬要兼容,怎么整?方案也有很多,稍微介绍下:

1、通过viewport + REM的方式来兼容。

目前这种兼容方案相对比较完美,适合新项目(老项目改用REM单位成本会比较高)。 淘宝M首页 就是这种方案。

在devicePixelRatio = 2 时,输出viewport

<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">

在devicePixelRatio = 3 时,输出viewport

<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">

同时通过设置对应viewport的rem基准值,这种方式就可以像以前一样轻松愉快的写1px了。

其他方案:

2、transform: scale(0.5)

实现方式

height:1px;
-webkit-transform: scaleY(0.5);
-webkit-transform-origin:0 0;
overflow: hidden;

圆角无法实现,hack代码多,实现4条边框比较闹心
只能单独使用,如果嵌套,scale的作用也会对包含的元素产生,不想要的影响,所以此种方案配合:after和:before独立使用较多,比如画一个商品的边框四条线,容器的after和before可以画2条线,利用容器的父元素的after、before再画2条线。

.after-scale{
  position: relative;
}
.after-scale:after{
    content:"";
    position: absolute;
    bottom:0px;
    left:0px;
    right:0px;
    border-bottom:1px solid #c8c7cc;
    -webkit-transform:scaleY(.5);
    -webkit-transform-origin:0 0;
}

3、box-shadow

实现方式

利用css 对阴影处理的方式实现0.5px的效果

底部一条线

-webkit-box-shadow:0 1px 1px -1px rgba(0, 0, 0, 0.5);

优点
基本所有场景都能满足,包含圆角的button,单条,多条线,
缺点
颜色不好处理, 黑色 rgba(0,0,0,1) 最浓的情况了。有阴影出现,不好用。

4、background-image

实现方式

设置1px通过css 实现的image,50%有颜色,50%透明

.border {
    background-image:linear-gradient(180deg, red, red 50%, transparent 50%),
    linear-gradient(270deg, red, red 50%, transparent 50%),
    linear-gradient(0deg, red, red 50%, transparent 50%),
    linear-gradient(90deg, red, red 50%, transparent 50%);
    background-size: 100% 1px,1px 100% ,100% 1px, 1px 100%;
    background-repeat: no-repeat;
    background-position: top, right top,  bottom, left top;
    padding: 10px;
}

优点
配合background-image,background-size,background-position 可以实现单条,多条边框。边框的颜色随意设置
缺点
如果有圆角的效果,很sorry 圆角的地方没有线框的颜色。都要写的代码也不少

5、用图片

实现方式

.border-image{
    border-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAECAYAAABP2FU6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAB5JREFUeNpiPnH8zH/G////MzAxAAHTyRNn/wMEGABpvQm9g9TJ1QAAAABJRU5ErkJggg==") 2 0 stretch;
    border-width: 0px 0px 1px;
}

可以通过修改图片来达到圆角的效果,但是由于图片的原因,压缩过后的图片边缘变模糊了(不放大的情况下不明显),需要引用图片或者base64,边框颜色修改起来不方便。

[原发布时间: 2016-02-20] 学习了解Node.js

什么是node.js

一个 “编码就绪” 服务器
Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念。它的目标是帮助程序员构建高度可伸缩的应用程序,编写能够处理数万条同时连接到一个(只有一个)物理机的连接代码。
我对于node的理解其实很简单,就是让Javascript脱离浏览器运行在服务器的一个平台,不是一种语言,node采用的Javascript引擎是来自Chrome的V8,并且不需要考虑Javascript兼容性问题,他就是一个服务器程序。

什么是v8?

V8引擎是Google用于其Chrome浏览器的底层JavaScript引擎。很少有人考虑JavaScript在客户机上实际做了些什么?实际上,JavaScript引擎负责解释并执行代码。Google使用V8创建了一个用C++编写的超快解释器,该解释器拥有另一个独特特征;您可以下载该引擎并将其嵌入任何应用程序。V8引擎并不仅限于在一个浏览器中运行。因此,Node实际上会使用Google编写的V8引擎,并将其重建为可在服务器上使用。太完美了!既然已经有一个不错的解决方案可用,为何还要创建一种新语言呢?

node.js能做什么

Node非常适合以下情况:在响应客户端之前,您预计可能有很高的流量,但所需的服务器端逻辑和处理不一定很多。
Node表现出众的典型示例包括:

RESTful API

提供 RESTful API 的 Web 服务接收几个参数,解析它们,组合一个响应,并返回一个响应(通常是较少的文本)给用户。这是适合 Node 的理想情况,因为您可以构建它来处理数万条连接。它仍然不需要大量逻辑;它本质上只是从某个数据库中查找一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的 API 需求。

Twitter 队列

想像一下像 Twitter 这样的公司,它必须接收 tweets 并将其写入数据库。实际上,每秒几乎有数千条 tweet 达到,数据库不可能及时处理高峰时段所需的写入数量。Node 成为这个问题的解决方案的重要一环。如您所见,Node 能处理数万条入站 tweet。它能快速而又轻松地将它们写入一个内存排队机制(例如 memcached),另一个单独进程可以从那里将它们写入数据库。Node 在这里的角色是迅速收集 tweet,并将这个信息传递给另一个负责写入的进程。想象一下另一种设计(常规 PHP 服务器会自己尝试处理对数据库本身的写入):每个 tweet 都会在写入数据库时导致一个短暂的延迟,因为数据库调用正在阻塞通道。由于数据库延迟,一台这样设计的机器每秒可能只能处理 2000 条入站 tweet。每秒处理 100 万条 tweet 则需要 500 个服务器。相反,Node 能处理每个连接而不会阻塞通道,从而能够捕获尽可能多的 tweets。一个能处理 50,000 条 tweet 的 Node 机器仅需 20 台服务器即可。

电子游戏统计数据

如果您在线玩过《使命召唤》这款游戏,当您查看游戏统计数据时,就会立即意识到一个问题:要生成那种级别的统计数据,必须跟踪海量信息。这样,如果有数百万玩家同时在线玩游戏,而且他们处于游戏中的不同位置,那么很快就会生成海量信息。Node 是这种场景的一种很好的解决方案,因为它能采集游戏生成的数据,对数据进行最少的合并,然后对数据进行排队,以便将它们写入数据库。使用整个服务器来跟踪玩家在游戏中发射了多少子弹看起来很愚蠢,如果您使用 Apache 这样的服务器,可能会 有一些有用的限制;但相反,如果您专门使用一个服务器来跟踪一个游戏的所有统计数据,就像使用运行 Node 的服务器所做的那样,那看起来似乎是一种明智之举。
以上内容皆属废话[部分资料来源于网络]

ps:在我看来,虽然我后台语言只接触过java,但是我觉得,统计、webapp、个人站点等常规网站都可以通过node.js来开发出来。
并且,node的开发语法非常适合前端人员低成本过渡到全栈开发工程师。

安装node

brew方式[Mac]
如果机器没有安装过node,那么首先brew install nvm安装nvm。
多版本管理器nvm,貌似Windows上好像不行,没测过。
其次需要在shell的配置文件(~/.bashrc, ~/.profile, or ~/.zshrc)中添加如下内容:

# For NVM
export NVM_DIR=~/.nvm
source $(brew --prefix nvm)/nvm.sh

重启终端,命令行下即可使用nvm,使用nvm install 进行对应的node版本安装。

其他系统请自行百度(以后有时间再补充)
https://nodejs.org/en/

[原发布时间: 2016-04-05] JS实现网页切出网站TITLE变化

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>这里是网站标题</title>
</head>
<body>
    <script type="text/javascript">
        document.body.onfocus = function(){
            document.title = '这里是网站标题';
        };
        document.body.onblur = function(){
            document.title = 'i miss you';
        };
    </script>
</body>
</html>

[原发布时间: 2016-03-21] 克隆JSON对象

一句话克隆JSON对象

var cloneData=JSON.parse(JSON.stringify(data))

假设原始数据为

var a = {
    r: 1,
    s: { 
        o: 2,
        p: 5,
        q: 8},
    t: [1, 3, 5, 7, 9]
}

如果我们这么赋值的话

var b = a;

那么 修改b, 则 a也随之改变
这是因为 他们的指向地址是一样的
如果 我们想克隆的话 应该这么做

var c = JSON.parse(JSON.stringify(a))

这样子我们就拿到了一个克隆的json对象,
原因是 先把json对象转换成字符串 然后再转换成json对象,这样子他的 地址指向就不一样了, 从而实现了克隆

[原发布时间: 2016-02-16] 通过Github Pages建立个人站点

对一个程序员来说 最好的简历就是个人博客和GitHub.

前言

想要进步的程序员都会有考虑过买一个服务器空间,配上自己的域名,那这里就是记录自己成长过程的空间。然而,买完域名,还要买空间,买完空间,还要维护空间,重点是,每年都要花一笔钱去阿里云购买空间。但是 GitHub 提供了 GitHub Pages 服务。

什么是GitHub Pages?

GitHub Pages 可以被认为是用户编写的、托管在github上的静态网页,用于介绍托管在GitHub的项目,不过,由于他的空间免费稳定,用来做搭建一个博客再好不过了。

为什么使用Github Pages?

  1. 搭建简单,而且免费;
  2. 支持静态脚本;
  3. 可以绑定你的域名;
  4. 有300M免费空间,资料自己管理,保存可靠;
  5. 学着用GitHub,享受GitHub的便利,上面有很多大牛,眼界会开阔很多;
  6. GitHub可是全球最大的技术交流平台。

创建一个GitHub站点

1.注册账户

地址: https://github.com
输入账号、邮箱、密码,然后点击注册按钮。

2.创建页面仓库

地址: https://github.com/new
这个仓库的名字需要和你的账号对应,规则如 username.github.io

3.设置配置

在settings中,就能看到GitHub Pages服务面板,
点击 Launch automatic page generator 启动自动页面生成器

4.创建用户页面

根据提示信息,输入一些内容,
点击继续,到下一个页面选择主题。
这些主题其实是生成一些css、js、image、html等文件到你的仓库中。
可以后期修改。
最后点击发布按钮。

5.查看效果

访问我们做出来的站点,地址为username.github.io

[原发布时间: 2016-03-08] HTML5前端开发基础–META全解

一、大众机型常用标签的设置

1、name之viewport

<meta name="viewport" content="">

说明:屏幕的缩放

content的几个属性:
• width viewport的宽度[device-width | pixel_value]width如果直接设置pixel_value数值,大部分的安卓手机不支持,但是ios支持;
•height – viewport 的高度 (范围从 223 到 10,000 )
•user-scalable [yes | no]是否允许缩放
•initial-scale [数值] 初始化比例(范围从 > 0 到 10)
•minimum-scale [数值] 允许缩放的最小比例
•maximum-scale [数值] 允许缩放的最大比例
•target-densitydpi 值有以下(一般推荐设置中等响度密度或者低像素密度,后者设置具体的值dpi_value,另外webkit内核已不准备再支持此属性)
— dpi_value 一般是70-400//没英寸像素点的个数
— device-dpi设备默认像素密度
— high-dpi 高像素密度
— medium-dpi 中等像素密度
— low-dpi 低像素密度

完整案例:

<meta name=“viewport” content=“width=device-width,height=device-height, user-scalable=no,initial-scale=1, minimum-scale=1, maximum-scale=1,target-densitydpi=device-dpi “>

2、name之format-detection忽略电话号码和邮箱

<meta name=”format-detection” content=”telephone=no”>

说明:忽略页面中的数字识别为电话号码

<meta name=”format-detection” content=”email=no”/>

说明:忽略页面中的邮箱格式为邮箱

也可以写成:

<meta name=“format-detection” content=“telphone=no, email=no”/>

3、name之设置作者姓名及联系方式

说明:设置作者姓名及联系方式

<meta name=”author” contect=”name, [email protected]” />

4、其他

<!-- 声明文档使用的字符编码 -->
<meta charset='utf-8'>

<!– 优先使用 IE 最新版本和 Chrome –>
<meta http-equiv=”X-UA-Compatible” content=”IE=edge,chrome=1″/>

<!– 页面描述 –>
<meta name=”description” content=”不超过150个字符”/>

<!– 页面关键词 –>
<meta name=”keywords” content=””/>

<!– 搜索引擎抓取 –>
<meta name=”robots” content=”index,follow”/>

<!– 启用360浏览器的极速模式(webkit) –>
<meta name=”renderer” content=”webkit”>

<!– 避免IE使用兼容模式 –>
<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<!– 不让百度转码 –>
<meta http-equiv=”Cache-Control” content=”no-siteapp” />

<!– 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 –>
<meta name=”HandheldFriendly” content=”true”>

<!– 微软的老式浏览器 –>
<meta name=”MobileOptimized” content=”320″>

<!– uc强制竖屏 –>
<meta name=”screen-orientation” content=”portrait”>
<!– QQ强制竖屏 –>

<meta name=”x5-orientation” content=”portrait”>
<!– UC强制全屏 –>
<meta name=”full-screen” content=”yes”>
<!– QQ强制全屏 –>

<meta name=”x5-fullscreen” content=”true”>
<!– UC应用模式 –>
<meta name=”browsermode” content=”application”>
<!– QQ应用模式 –>
<meta name=”x5-page-mode” content=”app”>

<!– 添加 RSS 订阅 –>
<link rel=”alternate” type=”application/rss+xml” title=”RSS” href=”/rss.xml”/>

<!– 添加 favicon icon –>
<link rel=”shortcut icon” type=”image/ico” href=”/favicon.ico”/>

<!– sns 社交标签 begin –>
<!– 参考微博API –>
<meta property=”og:type” content=”类型” />
<meta property=”og:url” content=”URL地址” />
<meta property=”og:title” content=”标题” />
<meta property=”og:image” content=”图片” />
<meta property=”og:description” content=”描述” />
<!– sns 社交标签 end –>

<!– Windows 8 磁贴颜色 –>
<meta name=”msapplication-TileColor” content=”#000″/>
<!– Windows 8 磁贴图标 –>
<meta name=”msapplication-TileImage” content=”icon.png”/>

<!– windows phone 点击无高光 –>
<meta name=”msapplication-tap-highlight” content=”no”>

二、ios系统的meta/link设置:

1、开启对web app程序的支持

<meta name=”apple-mobile-web-app-capable” content=”yes”>

说明:
网站开启对web app程序的支持,其实意思就是删除默认的苹果工具栏和菜单栏,全屏播放,开启全屏显示。设置完成后js可以通过访问只读属性window.navigator.standalone(boolean)来判断是否进入webapp展示状态。

2、 改变顶部状态条的颜色;

<meta name=”apple-mobile-web-app-status-bar-style” content=”black” />

说明:
在 web app 应用下状态条(屏幕顶部条)的颜色;
默认值为 default(白色),可以定为 black(黑色)和 black-translucent(灰色半透明);

3、设置“添加到主屏幕图标

Safari 浏览器有一个“添加到主屏幕”的功能,用户可以像保存书签一样把一个网站添加到主屏幕,下次用户直接点击主屏幕上的图标就能进入网站。

这个功能不仅方便用户快速访问我们的网站,而且也使我们的 WebApp 更像一个原生应用

因为 iOS 分辨率,所以 icon.png 图片的尺寸也各不相同,我们可以通过
sizes

属性来分别定义,iOS 系统会自动获取向匹配的图片:

<!-- iOS 图标 begin -->

<link rel=“apple-touch-icon-precomposed” href=“/apple-touch-icon-57×57-precomposed.png”/>

<!– iPhone 和 iTouch,默认 57×57 像素,必须有 –>

<link rel=“apple-touch-icon-precomposed” sizes=“114×114” href=“/apple-touch-icon-114×114-precomposed.png”/>

<!– Retina iPhone 和 Retina iTouch,114×114 像素,可以没有,但推荐有 –>

<link rel=“apple-touch-icon-precomposed” sizes=“144×144” href=“/apple-touch-icon-144×144-precomposed.png”/>

<!– Retina iPad,144×144 像素,可以没有,但推荐有 –>

<!– iOS 图标 end –></span>

添加到主屏幕后系统会默认给图片加上IOS相关的图标风格(比如圆角),如果需要系统直接展示原图使用apple-touch-icon-precomposed,如果需要系统添加风格使用apple-touch-icon。

扩展:

为用户加上提示

通过添加一个JavaScript代码来邀请用户添加到主屏幕,该库使用了HTML5的本地存储跟踪是否已经显示过了,以避免重复出现。

目前使用比较多和有在更新的一个库来自这里:http://cubiq.org/add-to-home-screen

4、设置桌面图标的标题,

为了在主屏达到最好的显示效果,
title
最好限制在六个中文长度内,超长的内容会被隐藏:

添加到主屏后的标题(iOS 6 新增)

<span style=“font-size:14px;”><meta name=“apple-mobile-web-app-title” content=“标题”></span>

5、设置启动画面

当用户点击主屏图标打开 WebApp 时,系统会展示启动画面,在未设置情况下系统会默认显示该网站的首页截图,当然这个体验不是很好,所以我们需要通过以下代码来自定义启动画面:

<link rel=“apple-touch-startup-image” href=“Startup.png” />

根据 iOS 设备的分辨率,其启动画面的图片尺寸也各不相同所以:

<!-- iOS 启动画面 begin -->

<link rel=“apple-touch-startup-image” sizes=“768×1004” href=“/splash-screen-768×1004.png”/>

<!– iPad 竖屏 768 x 1004(标准分辨率) –>

<link rel=“apple-touch-startup-image” sizes=“1536×2008” href=“/splash-screen-1536×2008.png”/>

<!– iPad 竖屏 1536×2008(Retina) –>

<link rel=“apple-touch-startup-image” sizes=“1024×748” href=“/Default-Portrait-1024×748.png”/>

<!– iPad 横屏 1024×748(标准分辨率) –>

<link rel=“apple-touch-startup-image” sizes=“2048×1496” href=“/splash-screen-2048×1496.png”/>

<!– iPad 横屏 2048×1496(Retina) –>

<link rel=“apple-touch-startup-image” href=“/splash-screen-320×480.png”/>

<!– iPhone/iPod Touch 竖屏 320×480 (标准分辨率) –>

<link rel=“apple-touch-startup-image” sizes=“640×960” href=“/splash-screen-640×960.png”/>

<!– iPhone/iPod Touch 竖屏 640×960 (Retina) –>

<link rel=“apple-touch-startup-image” sizes=“640×1136” href=“/splash-screen-640×1136.png”/>

<!– iPhone 5/iPod Touch 5 竖屏 640×1136 (Retina) –>

<!– iOS 启动画面 end –>

或者以下代码,具体没有实践,还需考证

<!!– iPhone SPLASHSCREEN–>

<!link href=”http://wlog.cn/html/”apple-touch-startup-image-320×460.png” media=“(device-width: 320px)” rel=“apple-touch-startup-image” />

<!!– iPhone (Retina) SPLASHSCREEN–>

<!link href=“apple-touch-startup-image-640×920.png” media=“(device-width: 320px) and (-webkit-device-pixel-ratio: 2)” rel=“apple-touch-startup-image” />

<!!– iPad (portrait) SPLASHSCREEN–>

<!link href=“apple-touch-startup-image-768×1004.png” media=“(device-width: 768px) and (orientation: portrait)” rel=“apple-touch-startup-image” />

<!!– iPad (landscape) SPLASHSCREEN–>

<!link href=“apple-touch-startup-image-748×1024.png” media=“(device-width: 768px) and (orientation: landscape)” rel=“apple-touch-startup-image” />

<!!– iPad (Retina, portrait) SPLASHSCREEN–>

<!link href=“apple-touch-startup-image-1536×2008.png” media=“(device-width: 1536px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)” rel=“apple-touch-startup-image” />

<!!– iPad (Retina, landscape) SPLASHSCREEN–>

<link href=”apple-touch-startup-image-1496×2048.png”media=”(device-width: 1536px)  and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)”rel=“apple-touch-startup-image” />

6、 添加智能 App 广告条 Smart App Banner(iOS 6+ Safari)

<meta name=“apple-itunes-app” content=“app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL”>

比较常用的meta

以下代码参考网址:view-source:三个w点adinnet点cn斜杠service斜杠3d点html

<!--[if lt IE 7 ]><html class="oldie ie ie6"> <![endif]-->

<!–[if IE 7 ]><html class=”oldie ie ie7″> <![endif]–>

<!–[if IE 8 ]><html class=”ie ie8″> <![endif]–>

<!–[if (gte IE 9)|!(IE)]><!–><html> <!–<![endif]–>

<head>

<meta http-equiv=“Content-Type” content=“text/html; charset=utf-8”>

<title></title>

<meta name=“keywords” content=“” />

<meta name=“description” content=“” />

<meta name=“title” content=“” />

<meta name=“author” content=“-06” />

<meta name=“Copyright” content=“” />

<!– 让IE浏览器用最高级内核渲染页面 还有用 Chrome 框架的页面用webkit 内核

================================================== —>

<meta http-equiv=“X-UA-Compatible” content=“IE=edge,chrome=1”>

<!– IOS6全屏 Chrome高版本全屏

================================================== —>

<meta name=“apple-mobile-web-app-capable” content=“yes”>

<meta name=“mobile-web-app-capable” content=“yes”>

<!– 让360双核浏览器用webkit内核渲染页面

================================================== —>

<meta name=“renderer” content=“webkit”>

<!– Mobile Specific Metas

================================================== —>

<!– !!!注意 minimal-ui 是IOS7.1的新属性,最小化浏览器ui –>

<meta name=“viewport” content=“width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui”>

<meta name=“format-detection” content=“telephone=no”>

<!– CSS

================================================== —>

<link href=“/css/reset.css” rel=“stylesheet” type=“text/css”>

<link href=“/css/magicwall.css” rel=“stylesheet” type=“text/css”>

<link  href=“/css/jquery.gridster.css” rel=“stylesheet” type=“text/css”>

<link href=“/css/case.css” rel=“stylesheet” type=“text/css”>

<link href=“/css/case_1280.css” rel=“stylesheet” type=“text/css”>

<link href=“/css/case_1024.css” rel=“stylesheet” type=“text/css”>

<link href=“/css/case_640.css” rel=“stylesheet” type=“text/css”>

<link href=“/css/case_320.css” rel=“stylesheet” type=“text/css”>

<link href=“/css/style_retina.css” rel=“stylesheet” type=“text/css”>



<!–[if lt IE 9]>

<script src=“http://cdn.bootcss.com/html5shiv/r29/html5.js”></script>

<![endif]–>

<!– Favicons

================================================== —>

<link rel=“shortcut icon” href=“favicon.ico” >

<!– Android 主屏图标

================================================== —>

<link rel=“icon” sizes=“196×196” href=“/images/apple-touch-icon-152×152.png”>

<!– IOS 主屏图标

================================================== —>

<link rel=“apple-touch-icon-precomposed” href=“/images/apple-touch-icon-76×76.png”>

<link rel=“apple-touch-icon-precomposed” sizes=“76×76” href=“/images/apple-touch-icon-76×76.png”>

<link rel=“apple-touch-icon-precomposed” sizes=“120×120” href=“/images/apple-touch-icon-120×120.png”>

<link rel=“apple-touch-icon-precomposed” sizes=“152×152” href=“/images/apple-touch-icon-152×152.png”>

<link rel=“apple-touch-startup-image” href=“/startup-748×1024.jpg”

media=“screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape)” >

<link rel=“apple-touch-startup-image” href=“/startup-768×1004.jpg”

media=“screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait)” >

或者说

<!-- 启用360浏览器的极速模式(webkit) -->

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

<!-- 避免IE使用兼容模式 -->

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->

<meta name="HandheldFriendly" content="true">

<!-- 微软的老式浏览器 -->

<meta name="MobileOptimized" content="320">

<!-- uc强制竖屏 -->

<meta name="screen-orientation" content="portrait">

<!-- QQ强制竖屏 -->

<meta name="x5-orientation" content="portrait">

<!-- UC强制全屏 -->

<meta name="full-screen" content="yes">

<!-- QQ强制全屏 -->

<meta name="x5-fullscreen" content="true">

<!-- UC应用模式 -->

<meta name="browsermode" content="application">

<!-- QQ应用模式 -->

<meta name="x5-page-mode" content="app">

<!-- windows phone 点击无高光 -->

<meta name="msapplication-tap-highlight" content="no">

[原发布时间: 2016-03-04] 根据主题颜色修改图片的颜色

在做一个移动端webapp应用,这里涉及到了,后台定制主题颜色,主题颜色不固定,
为了和对应的ios系统和安卓系统的原生app相对应,
所以我们要做使得图片的颜色也要根据主题颜色像自适应。

例如最后的效果的是这样子的
效果图
而图片是这样子的
默认图片

具体代码如下所示

var util = {
    /**
     * 根据主题颜色修改图片颜色
     * @param  {[type]}   imgUrl    图片url
     * @param  {[type]}   rgb_color 主题颜色
     * @param  {Function} callback  返回值 返回base64
     * @return {[type]}             [description]
     */
    changeImageColor: function (imgUrl, rgb_color, callback) {
        var threshold = 114; //默认颜色阀值 为 114 ->和默认图相关
        var img = new Image();
        img.src = imgUrl;
        //计算对应的通道值
        rgb_color = rgb_color || '#727272';
        var newR = parseInt('0x' + rgb_color.substr(1,2));
        var newG = parseInt('0x' + rgb_color.substr(3,2));
        var newB = parseInt('0x' + rgb_color.substr(5,2));
        //图片加载后进行处理
        img.onload = function () {
            var width = img.width, 
                height = img.height,
                canvas = document.createElement('canvas'),
                ctx = canvas.getContext('2d');
            canvas.width = width;
            canvas.height = height;
            // 将源图片复制到画布上
            ctx.drawImage(img, 0, 0, width, height);
            // 获取画布的像素信息
            var imageData = ctx.getImageData(0, 0, width, height);
            var data = imageData.data;
            // 对像素集合中的单个像素进行循环,每个像素是由4个通道组成,所以要注意
            var i = 0;
            while (i < data.length) {
                var r = data[i++],
                    g = data[i++],
                    b = data[i++],
                    a = data[i++];
                //计算透明度
                var alp = (255 - r) / (255 - threshold);
                //判断是否透明
                var isTransparent = (r == 255 && g == 255 && b == 255 && a == 255);
                if (isTransparent) { 
                    data[i - 1] = 0;
                } else {
                    data[i - 4] = newR;
                    data[i - 3] = newG;
                    data[i - 2] = newB;
                    data[i - 1] = (a !== 255) ? (255 - a) : (alp * 255); //处理透明的图片和不透明的图片
                }
            }
            // 将修改后的代码复制回画布中
            ctx.putImageData(imageData, 0, 0);
            // 图片导出为 png 格式
            var type = 'png';
            var imgData = canvas.toDataURL(type);
            // console.log(imgData); // 生成base64
            callback && callback(imgData);
        };
    }
};

//使用方式 其中 data、style 为通过api读取的值
util.changeImageColor(
    data.icon, //'http://127.0.0.1:5555/images/app/mc_forum_main_bar_button1_h.png',
    style.dz_skin_custom_main_color, //'#f51ca6', 
    function (data) {
        console.log(data);
    }
);

对于有人说,准备多个图片,通过css切换选择不一样的css,但是对于我这种后台返回,是类似于#5273ac这种颜色的方式,
所以我认为并不适用。

[原发布时间: 2016-03-12] Webpack配置React开发环境

Webpack 配置 React 开发环境

Webpack 是一个前端资源加载和打包工具,只需要相对简单的配置就可以提供前端工程化需要的各种功能

初始化项目 npm init

安装 Webpack:npm install -g webpack

Webpack 使用一个名为 webpack.config.js 的配置文件

假设我们在当前工程目录有一个入口文件 app.js,React 组件放置在一个 components/ 目录下,组件被 app.js 引用,要使用 app.js,我们把这个文件指定输出到 dist/app.min.js,Webpack 配置如下:

var webpack = require('webpack');
var path = require('path');
//输出HTML和CSS等等文件到路径的插件
var CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    //配置热替换服务器,每次改变JS文件都会自动AJAX刷新浏览器
    devServer: {
        historyApiFallback: true,
        hot: true,
        inline: true,
        progress: true,
        contentBase: './components',
        port: 9121
    },
    //sourcemap,正式打包请去掉此行或改成none
    devtool: 'source-map',
    //入口文件,需要处理的文件路径
    entry: [
        'webpack/hot/dev-server',
        'webpack-dev-server/client?http://localhost:9121',
        //上面2个是开发的时候用的热替换服务器
        path.resolve(__dirname, 'components/app.min.js')
    ],
    //输出文件位置
    output: {
        //绝对路径,用于输出到位置
        path: __dirname + '/dist',
        //服务路径,用于热替换服务器
        publicPath: '/',
        //输出文件名
        filename: './app.min.js'
    },
    //模块
    module: {
        //webpack的核心,所有的文件通过loader来处理编译
        loaders: [
            //js
            {
                //首先匹配文件后缀
                test: /\.js[x]?$/,
                //然后指定作用范围,这里可不写,但是范围越小速度越快
                include: path.resolve(__dirname, 'components'),
                //排除目录,exclude后将不匹配
                exclude: /node_modules/,
                //加载的loader,上面匹配到的文件都通过下面的loader来处理编译,这里是babel-es6+react
                loader: 'babel?presets[]=react,presets[]=es2015'
            },
            //.css 文件使用 style-loader 和 css-loader 来处理
            { test: /\.css$/, loader: 'style!css' },
            //图片文件使用url-loader 处理 '?limit=8192'表示将所有小于8kb的图片都转为base64形式
            {test: /.(png|jpg)$/, loader: 'url-loader?limit=8192'}
        ]
    },
    //插件
    plugins: [
        //热替换插件
        new webpack.HotModuleReplacementPlugin(),
        //输出文件插件,最顶上有引入
        new CopyWebpackPlugin([
            { from: './index.html', to: 'index.html' },
        ]),
        //以下代码为压缩代码插件,在打包的时候用,开发环境下会减慢编译速度
        //new webpack.optimize.UglifyJsPlugin({
        //    这里是去除错误提示的配置,具体看webpack文档
        //    compress: {
        //        warnings: false
        //    }
        //}),
    ]
};

安装模块

npm install react --save-dev
注意 react 0.14版本 把react 拆分成 react 和 react-dom
npm install react-dom --save-dev

npm install webpack --save-dev
npm install webpack-dev-server --save-dev

npm install copy-webpack-plugin --save-dev

npm install babel-core --save-dev
npm install babel-loader --save-dev
npm install babel-preset-es2015 --save-dev
npm install babel-preset-react --save-dev

npm install style-loader --save-dev //style-loader加载器
npm install css-loader --save-dev //css-loader加载器
npm install url-loader --save-dev //url-loader加载器 -> 图片

修改package

"scripts": {
    "build": "webpack -p",
    "start": "webpack-dev-server --devtool eval --progress --hot --colors "
},

一个简单的hello world

创建一个简单的页面 index.html 文件
代码为

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
        <title>learn-react</title>
    </head>
    <body>
        <div id="app"></div>
    </body>
    <script type="text/javascript" src="app.min.js"></script>
</html>

然后在 components 文件夹下 创建 app.js 文件

'use strict'

import ReactDOM from 'react-dom';
import React from 'react';

export default class App extends React.Component {

    constructor() {
        super();
        this.state = {};
    }
    render() {
        return (
            <div>Hello World</div>
        )
    }
};
//插入到页面中
ReactDOM.render(<App />, document.getElementById('app'));

运行后 页面出现 Hello World
Hello World

[原发布时间: 2016-04-13] ==和===到底有什么区别

以前一直以为==和===很简单,也很少去做对象比较
[]==![] 这个表达式结果是什么?

于是去翻了下==和===的比较

1. 对于string,number等基础类型,==和===是有区别的

1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等
2)同类型比较,直接进行“值”比较,两者结果一样

2. 对于Array,Object等高级类型,==和===是没有区别的

进行“指针地址”比较

3. 基础类型与高级类型,==和===是有区别的

1)对于==,将高级转化为基础类型,进行“值”比较
2)因为类型不同,===结果为false
想要得到结果很简单,chrome打开console下输入表达式,答案是true,为什么呢?
3-(2)答案在里面的值比较,右边![]肯定是个布尔值false,那么左边为什么也是false呢?
原来是valueOf和toString方法调用,这个地方先调用valueOf,Array的valueOf还是数组本身,然后调用了toString方法
得到结果是“”,“” == false,结果就是true了

[原发布时间: 2016-02-21] 改变NPM的镜像

因为国内特别的网路环境,梯子不给力请用淘宝 NPM 镜像。

临时使用:

npm --registry https://registry.npm.taobao.org install express

持久使用:

npm config set registry https://registry.npm.taobao.org

配置后可通过下面方式来验证是否成功

npm config get registry

[原发布时间: 2016-03-14] HTML锚点的使用

HTML5已经去掉name属性,实现锚点时请使用id。

同页面:

<a href="#q1">问题一?</a> 
.......
<div id="q1">问题一的解答</div> 

不同页面:

a的内容

<a href="b#q1">问题一?</a> 

b的内容

<a id="q1">问题一的解答</a>

注:添加锚点,起始位置最好用标记来写(适配移动端)。

[原发布时间: 2016-03-19] 前后端模板引擎选型

讨论模板引擎,就是讨论api模式。至于双向绑定,以及是否使用vdom,完全是另外一个层面的事情。经过多种层次的实践,笔者建议,干脆选一种最方便模板用作创作,另外的框架使用的模板则用这种模板自动翻译或生成。

【早期CGI系,原始的拼接字符串风格;简单插值可使用多行模板字符串】

if ( list.length ) {
  html+='<ol>';
  for ( n=0; n<list.length; ++n ) {
    html+=`
      <li>
        ${ list[n] }
      </li>
    `;
  }
  html+='</ol>';
}

【亲民XSP系(如PHP/ASP/JSP),拼接字符串模式的反转语法(糖);逻辑视觉比例过高】

<% if ( list.length ) { %>
  <ol>
    <% for ( n=0; n<list.length; ++n ) { %>
      <li>
        <%= list[n] %>
      </li>
    <% } %>
  </ol>
<% } %>

【简约语法(如EJS),再度简约;高级语法有限,通常难自定义拓展】

{{#if list.length}}
  <ol>
    {{#each list item}}
      <li>
        {{ item }}
      </li>
    {{/each}}
  </ol>
{{/if}}

【丧心病狂的创造语法(如Jade);完全新语法,大量强大功能,极度简洁,投奔与否见仁见智】

- if list.length
  ol.
    - each item in list
      li= item

【返璞归真(如Vue;确切说是如Vue的模板解读方式),基于DOM属性的指令语法,前端模板优势一目了然】

<ol v-if="list.length">
  <li v-for="item in list">
    {{ item }}
  </li>
</ol>

【另辟蹊径,回归完全亲和的JS胶水语法,笔者作为选用Vue的服务器端补充(以及面向未来的多客户端通用原型模板;不过还不确定是否应当合并IE6-9和先进浏览器模板,还是索性分离更为实用);任意拓展、组件即数据即函数。】

ol({v_if:`list.length`},
  li({v_for:`item in list`},
    '{{ item }}'
  )
)

更完整的例子:

template(
  '<!DOCTYPE html>',
  html(
    head(
      meta({charset:'utf-8'})
    ),
    body(
      '原始字符',
      '{{ $数据.$转义变量 }}',
      ol({v_if:`'length' in $数据.$列表`,v_bind$title:`$数据.$标题`},
        li({v_for:`_值 in $数据.$列表`,v_bind$title:`$index`},
          '{{ _值 }}'
        )
      ),
      template({v_for:`_便捷临时变量 in {_:$数据.$浅层.$深层}`},
        '{{ _便捷临时变量 }}'
      )
    )
  )
)

唯一的问题是……如果说XSP系是阳火旺的话,那这种方案就可以说是阴火旺了。js实现的html结构过于简练,反而和变量混淆不清,和XSP逻辑比重过多,殊途同归。

[原发布时间: 2016-02-16] 利用Hexo来美化Github Pages的个人站点

上一篇文章已经说了如何利用GitHub Pages服务来搭建免费站点
这一次我们要使用 Hexo+GitHub+多说 来搭建免费博客

要用到的模块

Hexo 是一款基于nodejs的快速、简单、强大的博客系统框架。
GitHub 代码仓库。
多说 一个第三方评论系统。

安装Hexo来生成Blog

安装

首先 通过npm 进行 全局安装 hexo
npm install hexo -g
安装结束后,初始化一个blog项目
hexo init blog
进入 blog 项目里
cd blog
初始化安装第三方支撑库
npm install
启动服务器
hexo server

blog项目的文件目录结构为:
  • _config_yml // 注配置文件
  • db.json // 数据
  • debug.log // 调试日志
  • node_mudules // nodejs 相关依赖
  • package.json // 配置依赖
  • scaffolds // 脚手架 - 也就是一个工具模板
  • source // 存放blog正文的地方
  • themes // 存放皮肤的地方

默认访问地址: http://localhost:4000

页面打不开

启动后,进行访问页面,会发现页面打开缓慢,这是因为我们电脑没有翻墙。
页面默认使用了ajax.google.com 下的js包。
因此我们要把包删掉。
解决办法:
进入你刚新建好的 blog根目录 ,进入themes/landscape/layout/_partial中,
找到 after-footer.ejs
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"> </script>
替换成
<script src="http://cdn.bootcss.com/jquery/2.1.1/jquery.min.js“ > </script>
找到 header.ejs
注释掉或者删掉下面这句css引用
<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel=”stylesheet” type=”text/css”>
重新 hexo server 之后。
访问 http://localhost:4000 就会看到blog主页了。

新建文章

写一篇文章的话 通过 hexo new <title> 来实现
例如:hexo new hello
然后 我们可以这个文件进行修改了

title: hello
date: 2016-02-16 18:50:48
tags:
- tag1
- tag2
- tag3
categories:
- 目录
__

// 你的内容
<!--more--> // 以上为摘要

新建页面

创建一个新的页面的话 通过 hexo new page <title> 来实现
例如:hexo new page about

删除文章

首先删除目录下的 db.json 文件
然后 执行hero clean
删掉不想要的md文件
然后 启动服务器 或 静态处理 就可以了

静态处理

因为我们的blog要部署到github静态服务器上面,所有我们还要将页面进行静态化
hexo 为我们提供了 hexo g 的方法。进入blog根目录 执行hexo g
那么在blog根目录下 就会生成public文件夹, 这里面就是生成的静态文件。

部署到GitHub上

部署

hexo已经集成了发布到github的配置,只需要修改根目录下的_config.yml 文件
增加配置信息,注意hexo3 的配置有所改动 此为hexo3 的配置信息

# Deployment
## Docs: http://hexo.io/docs/deployment.html
deploy:
  type: git
  repo: your-github-url

部署到远程站点hexo deploy

注意:
hexo 版本号3以上 会出现 hexo ERROR Deployer not found: github
你需要安装 npm install hexo-deployer-git --save
并且将deploy 的 type由github改为git

域名指向

在github blog项目下新建一个CNAME文件 内容为你的域名
然后去 万网解析一下你的域名
注意:
解析类型为 -> CNAME
解析地址为 -> username.github.io

安装插件

多说

评论插件多说为 hexo量身打造了一套解决方案
查看教程

rss

rss的安装非常简单 ,已经有人做好了插件,安装只需一步。
npm install hexo-generator-feed --save
启动服务器,用浏览器打开 http://localhost:4000/atom.xml, 就可以看到RSS已经生效了.

sitemap

同样是一条命令,就可以完成。

google 的 sitemap -> npm install hexo-generator-sitemap 启动服务器,用浏览器打开 用浏览器打开 http://localhost:4000/sitemap.xml 发现site已经生效。

baidu 的 sitemap -> npm install hexo-generator-baidu-sitemap 启动服务器,用浏览器打开 用浏览器打开 http://localhost:4000/baidusitemap.xml 发现site已经生效。

其中sitemap.xml适合提交给谷歌搜素引擎,baidusitemap.xml适合提交百度搜索引擎。

[原发布时间: 2016-04-08] ES6箭头函数的使用和注意点

ES6可以使用“箭头”(=>)定义函数,注意是函数,不要使用这种方式定义类(构造器)。

一、语法

1.具有一个参数的简单函数

var single = a => a
single('hello, world') // 'hello, world'

2.没有参数的需要用在箭头前加上小括号

var log = () => {
    alert('no param')
}

3.多个参数需要用到小括号,参数间逗号间隔,例如两个数字相加

var add = (a, b) => a + b
add(3, 8) // 11

4.函数体多条语句需要用到大括号

var add = (a, b) => {
    if (typeof a == 'number' && typeof b == 'number') {
        return a + b
    } else {
        return 0
    }
}

5.返回对象时需要用小括号包起来,因为大括号被占用解释为代码块了

var getHash = arr => {
    // ...
    return ({
        name: 'Jack',
        age: 33
    })
}

6.直接作为事件handler

document.addEventListener('click', ev => {
    console.log(ev)
})

7.作为数组排序回调

var arr = [1, 9 , 2, 4, 3, 8].sort((a, b) => { 
    if (a - b > 0 ) {
        return 1
    } else {
        return -1
    }
})
arr // [1, 2, 3, 4, 8, 9]

二、注意点

1.typeof运算符和普通的function一样

var func = a => a
console.log(typeof func); // "function"

2.instanceof也返回true,表明也是Function的实例

console.log(func instanceof Function); // true

3.this固定,不再善变

obj = {
    data: ['John Backus', 'John Hopcroft'],
    init: function() {
        document.onclick = ev => {
            alert(this.data) // ['John Backus', 'John Hopcroft']
        }
        // 非箭头函数
        // document.onclick = function(ev) {
        //     alert(this.data) // undefined
        // }
    }
}
obj.init()

这个很有用,再不用写me,self,_this了,或者bind。

4.箭头函数不能用new

var Person = (name, age) => {
    this.name = name
    this.age = age
}
var p = new Func('John', 33) // error

5.不能使用argument

var func = () => {
    console.log(arguments)
}
func(55) //

对于5,在Firefox36里测试是可以输出55的,貌似并没有这个限制

[原发布时间: 2016-02-24] 如何判断微信android和IOS

微站点的开发,我们需要知道当前的浏览器是微信内置的浏览器,那么如何判断呢?

微信内置浏览器的 User Agent

首先需要获取微信内置浏览器的User Agent,经过在 iPhone 上微信的浏览器的检测,它的 User Agent 是:
Mozilla/5.0 (iPhone; CPU iPhone OS 6_1_3 like Mac OS X)
AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B329 MicroMessenger/5.0.1
所以通过识别 MicroMessenger 这个关键字来确定是否微信内置的浏览器了。

function isWeiXin() {
    var ua = window.navigator.userAgent.toLowerCase();
    return (ua.match(/MicroMessenger/i) === 'micromessenger');
}

判断IOS系统

通过 window.navigator.userAgent.match(/iP(hone|od|ad)/) 来判断是否是ios系统

function isIos() {
    var ua = window.navigator.userAgent.toLowerCase();
    return (ua.match(/iP(hone|od|ad)/i));
}

获取IOS版本号

function getVersion() {
    var version = parseFloat(String(window.navigator.userAgent.match(/[0-9]_[0-9]/)).split('_')[0] + '.' + String(window.navigator.userAgent.match(/[0-9]_[0-9]/)).split('_')[1]);
    return version;
}

[原发布时间: 2016-03-11] JS根据身份证号码获取出生日期、年龄以及性别

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>js根据身份证号码获取出生日期、年龄以及性别</title>
</head>
<body>
     <input type="text" id="code"><br/>
     <input type="button" value="获取出生日期以及年龄" onclick="getCode()">
        <script type="text/javascript">
             function getCode(){
                var code=document.getElementById("code").value;
                var year=code.substring(6,10);
                alert(year);
                var month=code.substring(10,12);
                alert(month);
                var day=code.substring(12,14);
                alert(day);
                var sui=2015-year+1;
                alert(sui);
                var sexName=code.substring(16,17);
                var sex=(sexName%2==0?"女":"男");
                alert(sex);
                alert("我的出生日期是"+year+"年"+month+"月"+day+"日"+",今年"+sui+"岁了"+",性别是"+sex);
             }
        </script>
</body>
</html>

[原发布时间: 2016-03-22] JS判断屏幕旋转

判断屏幕是否旋转

function orientationChange() {
    switch(window.orientation) {
      case 0:
            alert("肖像模式 0,screen-width: " + screen.width + "; screen-height:" + screen.height);
            break;
      case -90:
            alert("左旋 -90,screen-width: " + screen.width + "; screen-height:" + screen.height);
            break;
      case 90:
            alert("右旋 90,screen-width: " + screen.width + "; screen-height:" + screen.height);
            break;
      case 180:
          alert("风景模式 180,screen-width: " + screen.width + "; screen-height:" + screen.height);
          break;
    };};

添加事件监听

addEventListener('load', function(){
    orientationChange();
    window.onorientationchange = orientationChange;
});

[原发布时间: 2016-03-30] 解决UC浏览器、微信浏览器使用display:flex

在android平台的uc浏览器和微信浏览器中使用display: flex;会出问题。

使用display: flex;的时候需要加上display: -webkit-box;

使用flex: 1;的时候要加上:

-webkit-box-flex: 1;      
-moz-box-flex: 1;         
-ms-flex: 1;  

使用align-items: center;的时候需要加上:-webkit-box-align: center;

使用flex-direction: column;的时候需要加上:

-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;

这里有个demo大家可以看一下
请点击:测试页面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  <title>Demo for flex on uc</title>
  <style type="text/css">
  html,body{
    padding: 0;
    margin: 0;
  }
  .demo1{
    background-color: yellow;
    text-align: center;
    height: 80px;    
    display: -webkit-flex;     
    display: flex;
    -webkit-align-items: center;
    align-items: center;
    /* for uc */
    display: -webkit-box;  
    -webkit-box-align: center;
  }
  .demo1>div{
    background-color: green;
    margin: 2px;       
    -webkit-flex: 1;          
    flex: 1;         
    /* for uc */
    -webkit-box-flex: 1;      
    -moz-box-flex: 1;         
    -ms-flex: 1;                
  }
  .demo2{
    background-color: yellow;
    width: 80px;
    height: 200px;
    display: -webkit-flex;     
    display: flex;
    -webkit-flex-direction: column;
    flex-direction: column;
    -webkit-align-items: center;
    align-items: center;
    /* for uc */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -moz-box-orient: vertical;
    box-orient: vertical;
    -webkit-box-align: center;
  }
  .demo2>div{
    background-color: green;
    width: 40px;
    margin: 2px;       
    -webkit-flex: 1;          
    flex: 1;         
    /* for uc */
    -webkit-box-flex: 1;      
    -moz-box-flex: 1;         
    -ms-flex: 1;    
  }
  </style>
</head>
<body>
<h2>左右排列,上下居中</h2>
<div class="demo1">
  <div>flex</div>
  <div>flex</div>
  <div>flex</div>
  <div>flex</div>
  <div>flex</div>
</div>
<h2>上下排列,左右居中</h2>
<div class="demo2">
  <div>flex</div>
  <div>flex</div>
  <div>flex</div>
  <div>flex</div>
  <div>flex</div>
</div>
</body>
</html>

[原发布时间: 2016-02-21] NPM基本使用梳理备忘录

npm使用笔记

1.npm是node的包管理工具,会随node一起装到电脑上

2.如果要使用别人的插件,别人的包:

基本安装:npm install xxoo,安装在当前目录,其外层会自动创建一个node_modules文件夹
全局安装:npm install -g xxoo,插件可以在任何目录被调用,即全局
依赖安装:npm install -save xxoo,安装在当前目录,安装的插件会被写入package.json文件

3.拷贝了一个基于npm的项目,项目中只有package.json文件,如何下载依赖?

进入项目目录,执行命令:

npm install

4.如何在自己的项目中使用npm?

进入项目目录执行:npm init,并根据提示完成package.json文件的构建

5.自己写了个npm插件,如何发布?

https://www.npmjs.com/注册账号,然后进入自己用npm管理的项目目录:

1. 执行登录命令:npm adduser,根据提示填写用户名和密码
2. 执行发布插件命令:npm publish,插件会被发布到https://www.npmjs.com/,供自己和其他人下载安装(如果发布失败,多是因为插件名称重复)
3. 取消发布命令:npm unpublish,插件会从https://www.npmjs.com/删除

更多资料:http://www.runoob.com/nodejs/nodejs-npm.html

[原发布时间: 2016-03-16] 网页常用的防复制代码

最牛的防复制代码

1.将此代码粘贴到body中可以有效防选中防复制和防鼠标右键

<script type="text/javascript">
    document.body.oncontextmenu = 
    document.body.ondragstart = 
    document.body.onselectstart = 
    document.body.onbeforecopy = 
    function () { return false; };

    document.body.onselect = 
    document.body.oncopy = 
    document.body.onmouseup = 
    function () { document.selection.empty(); };
</script>

2.将此代码粘贴到body中可以有效防选中防复制和防鼠标右键

<script language="JavaScript">
    document.oncontextmenu = new Function('event.returnValue=false;');
    document.onselectstart = new Function('event.returnValue=false;');
</script>

3.禁止查看网页源文件代码,插入网页即可。

<body leftmargin="2" topmargin="0" marginwidth="0" marginheight="0" oncontextmenu="return false" ondragstart="return false" onselectstart ="return false" onselect="document.selection.empty()" oncopy="document.selection.empty()" onbeforecopy="return false" onmouseup="document.selection.empty()">
<noscript><iframe src="/blog/*>";</iframe></noscript>

4.将彻底屏蔽鼠标右键

oncontextmenu="window.event.returnvalue=false"
<table border oncontextmenu=return(false)><td>no</table> //可用于Table

5.取消选取、防止复制

<body onselectstart="return false">

6.不准粘贴

onpaste="return false"

7.防止复制

oncopy="return false;" oncut="return false;"

8.防止被人frame

<SCRIPT LANGUAGE=javascript><!-- if (top.location != self.location)top.location=self.location; // --></SCRIPT>

9.网页将不能另存为

<noscript><iframe src="/blog/*.html>";</iframe></noscript>

10.改变连接是状态栏的显示内容

<a href="http://www.toyean.com" onMo ... ;window.status="输入连接状态栏显示内容&rsquo;;return true">

11.禁止网页中目标对象被下载(如图片)

下面的代码将帮助你禁止网页中目标对象被下载:

<a href="javascript:void(0)" onMouseDown="alert('对不起!图片不能下载!')"><img src="图片地址" alt="" /></a>

12.页面禁止刷新完全,最好在pop出来的窗口里用,没工具栏的

<body onkeydown="KeyDown()" onbeforeunload="location=location"
oncontextmenu="event.returnValue=false">
<script language="Javascript"><!-- 
function KeyDown(){ 
if ((window.event.altKey)&& 
     ((window.event.keyCode==37)||   
      (window.event.keyCode==39))){alert("请访问我的主页"); 
    event.returnValue=false; 
    } 
if ((event.keyCode==8)||(event.keyCode==116)){//屏蔽 F5 刷新键 
    event.keyCode=0; 
    event.returnValue=false; 
    } 
if ((event.ctrlKey)&&(event.keyCode==78)){   //屏蔽 Ctrl+n 
    event.returnValue=false; 
    } 
if ((event.shiftKey)&&(event.keyCode==121)){ //屏蔽 shift+F10 
    event.returnValue=false; 
    } 
} 
</script> 
</body>

[原发布时间: 2016-02-17] 使用NexT主题美化Hexo框架站点

Hexo主题非常多,可以参考丰富多彩的Hexo主题
推荐使用NexT为主题,因为他的特色是 给我的感觉就是 精简

NexT主题安装使用

从 GitHub 下载

$ cd your-hexo-site
$ git clone https://github.com/iissnan/hexo-theme-next themes/next

更改站点 _config.yml 中的 theme 字段设置为 next

theme: next

NexT的配置

进入配置阶段,最好的文档还是官方文档,简单得不能再细致了
网址为:http://theme-next.iissnan.com/

NexT主题创建 “留言” 页面

让你的page页面也支持 多说 / DISQUS 评论系统

NexT主题默认page模板最新的版本是支持评论的,如生成的标签云页面,分类页面,about页面等。
想让页面没有评论 只需要在头部加入

comments: false

找到你NexT主题_config.yml(主意是NexT主题的_config.yml,不是hexo站点目录下的_config.yml),文件路径your-hexo-site/themes/next/_config.yml,添加 guestbook 到 menu 中,如下:

menu:
  home: /
  #categories: /categories
  about: /about
  archives: /archives
  # tags: /tags
  #commonweal: /404.html
  guestbook: /guestbook

找到你NexT主题zh-Hans.yml文件(我的网站是简体语言的),文件路径your-hexo-site/themes/next/languages/zh-Hans.yml,添加 guestbook: 留言 到 menu 中,如下:

menu:
  home: 首页
  archives: 归档
  categories: 分类
  tags: 标签
  about: 关于
  commonweal: 公益404
  guestbook: 留言

新建一个 guestbook 页面:

hexo new page "guestbook"

NexT主题添加腾讯空间404公益页面

原来主题也有介绍了如何在增加腾讯公益404页面,但是整个页面跳了出去,我个人比较喜欢下面404页面嵌在内页这种风格
腾讯空间404
使用方法一样,新建404.html页面,将下面代码拷进去保存,放到主题的source目录下即可:

<!DOCTYPE HTML>
<html>
<head>
    <title>404 - arao'blog</title>
    <meta name="description" content="404错误,页面不存在!">
    <meta http-equiv="content-type" content="text/html;charset=utf-8;"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="robots" content="all" />
    <meta name="robots" content="index,follow"/>
</head>
<body>
    <script type="text/javascript" src="http://qzonestyle.gtimg.cn/qzone_v6/lostchild/search_children.js" charset="utf-8"></script>
</body>
</html>

hexo NexT主题首页title的优化

更改index.swig文件,文件路径是your-hexo-site\themes\next\layout,将下面代码

{% block title %} {{ config.title }} {% endblock %}

改成

{% block title %} {{ config.title }} - {{ theme.description }} {% endblock %}

这时候你的首页标题会更符合网站名称 - 网站描述这习惯。
进阶,做了seo优化,把关键词也显示在Title标题里,可改成

{% block title %} {{ theme.keywords }} - {{ config.title }} - {{ theme.description }} {% endblock %}

注意:别堆砌关键字,整个标题一般不超过80个字符,可以通过chinaz的seo综合查询检查。

[原发布时间: 2016-03-03] RGB和RGBA之间的转换

项目需要用到透明度,但是服务端给我的都是颜色,没有给关于透明度的色系,无奈之下,自己写了一个转换

代码如下:

var util = {
    rgb2Rgba: function (rgb_color, alp) {
        //注:rgb_color的格式为#FFFFFFF 或 #FFF
        if (rgb_color.length !== 7 && rgb_color.length !== 4 ) return null;
        if (rgb_color.length === 4) {
            rgb_color = rgb_color.substr(1,1) + rgb_color.substr(1,1) +
                        rgb_color.substr(2,1) + rgb_color.substr(2,1) +
                        rgb_color.substr(3,1) + rgb_color.substr(3,1);
        }
        var r = parseInt('0x' + rgb_color.substr(1,2));
        var g = parseInt('0x' + rgb_color.substr(3,2));
        var b = parseInt('0x' + rgb_color.substr(5,2));
        var a = alp || 1;//为透明度
        return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
    },  
    rgba2Rgb: function (rgba_color) {
        //注:rgba_color的格式为rgba(0, 0, 0, 0.1)
        var BGcolur = 1;
        var arr = rgba_color.split('(')[1].split(')')[0].split(',');
        var a = arr[3];
        var r = BGcolur * (1 - a) + arr[0] * a;
        var g = BGcolur * (1 - a) + arr[1] * a;
        var b = BGcolur * (1 - a) + arr[2] * a;
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    }
};

[原发布时间: 2016-02-28] iframe在移动端上不能滚动的问题

今天要在web中嵌套一个网址或本地HTML,用到了iframe,电脑上测试滚动是好使的。而在手机上无法滚动。经过查询,发现原来在html5中的iframe已经只有剩下src的属性。

解决办法:
在iframe外加一层div,设置样式-webkit-overflow-scrolling:touch; overflow: scroll;
让超出div的内容可以通过touch来滚动。

<div id="scrollee" style="width:300px;height:300px;-webkit-overflow-scrolling:touch; overflow: scroll;">  
    <iframe id="object" height="90%" width="100%" type="text/html" src="https://www.baidu.com/"></iframe>
</div>  

[原发布时间: 2016-02-29] 关于iframe在移动端子页面宽度过宽问题

处理iframe子页面过宽问题

解决方案

var iframe = document.createElement('iframe');
    iframe.style.border = '0';
    iframe.style.width = '1px';
    iframe.style.height = '100%';
    iframe.style.minWidth = '100%';
    iframe.width = '100%';
    if(isMobileSafari()){
        iframe.scrolling = 'no';
    }

function isMobileSafari() {
    var ua = window.navigator.userAgent.toLowerCase();
    return (ua.match(/iP(hone|od|ad)/i) && (ua.indexOf('Safari') > -1));
}

[原发布时间: 2016-02-23] CSS中px和em,rem之间的区别

国内的设计师大都喜欢用px,而国外的网站大都喜欢用em和rem,那么三者有什么区别,又各自有什么优劣呢?

PX特点

  1. IE无法调整那些使用px作为单位的字体大小;
  2. 国外的大部分网站能够调整的原因在于其使用了em或rem作为字体单位;
  3. Firefox能够调整px和em,rem,但是96%以上的**网民使用IE浏览器(或内核)。

**px像素(Pixel)。相对长度单位。**像素px是相对于显示器屏幕分辨率而言的。(引自CSS2.0手册)
**em是相对长度单位。相对于当前对象内文本的字体尺寸。**如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。(引自CSS2.0手册)
任意浏览器的默认字体高都是 16px 。所有未经调整的浏览器都符合: 1em=16px。
那么12px=0.75em,10px=0.625em。
为了简化font-size的换算,需要在css中的body选择器中声明Font-size=62.5%,这就使em值变为 16px*62.5%=10px, 这样12px=1.2em, 10px=1em, 也就是说只需要将你的原来的px数值除以10,然后换上em作为单位就行了。

EM特点

  1. em的值并不是固定的;
  2. em会继承父级元素的字体大小。

所以我们在写CSS的时候,需要注意两点:

  1. body选择器中声明Font-size=62.5%;
  2. 将你的原来的px数值除以10,然后换上em作为单位;
  3. 重新计算那些被放大的字体的em数值。避免字体大小的重复声明。
    也就是避免1.2 * 1.2= 1.44的现象。比如说你在#content中声明了字体大小为1.2em,那么在声明p的字体大小时就只能是1em,而不是1.2em, 因为此em非彼em,它因继承#content的字体高而变为了1em=12px。

例如:

html { font-size: 100%; }
.box-0 {
    height: 1em; /* 此时height等于16px */
} 
.box-1 { 
    font-size: 0.625em; /* 此时基准字号以变更为16*0.625=10px */ 
    height: 1em; /* 此时实际height等于10px */
}

REM特点

rem是CSS3新增的一个相对单位(root em,根em),这个单位引起了广泛关注。这个单位与em有什么区别呢?
区别在于使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素。这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。
目前,除了IE8及更早版本外,所有浏览器均已支持rem。对于不支持它的浏览器,应对方法也很简单,就是多写一个绝对单位的声明。这些浏览器会忽略用rem设定的字体大小。
下面就是一个例子:

.box {
    font-size: 14px; /* 用来兼容ie678 */
    font-size: 0.875rem; 
}

注意:
选择使用什么字体单位主要由你的项目来决定,如果你的用户群都使用最新版的浏览器,那推荐使用rem,如果要考虑兼容性,那就使用px,或者两者同时使用。

[原发布时间: 2016-02-22] 如何去除移动端链接a标签产生带色边框

点击链接a标签时,会有一个很丑的边框出现,很是影响页面美观。

样式代码如下

a{
    border:none;
    -webkit-tap-highlight-color: rgba(0,0,0,0);
    -webkit-tap-highlight-color:transparent;
    outline:none;
}

会出现这样的问题是因为:
-webkit-tap-highlight-color是ios和android下点击元素时出现的阴影。
-webkit-tap-highlight-color: rgba(0,0,0,0);-webkit-tap-highlight-color:transparent; 都可以将该阴影透明化,进而解决那个丑丑的边框问题。

[原发布时间: 2016-04-15] 微信iframe问题之子页面过宽

今天在测试的时候 遇到了一个奇葩的问题
微信iframe 子页面的URL 设定为百度
但是在微信浏览器里子页面过宽
这是因为 默认iframe的滚动条宽度被计算进去了
使用传统滚动条浏览器有这个问题 但是按理说微信浏览器应该没那么低端的。。。
主要解决方案 就是

iframe的scrolling属性 设为 no

[原发布时间: 2016-03-29] html拨打电话与发送短信

1,拨打电话

<a title="热线电话" href="tel://13500000000" data-ajax="false">
    <dl>
        <dt><img alt="热线电话" src="img/icon_4.png"></dt>
        <dd>热线电话</dd>
    </dl>
</a>

2,发送短信

<a title="在线留言" href="sms:13500000000" data-ajax="false">
    <dl>
        <dt><img alt="在线留言" src="img/icon_5.png"></dt>
        <dd>发送短信</dd>
    </dl>
</a>

[原发布时间: 2016-02-27] 使用CSS伪类实现三角

文字不重要,重点看代码

<!DOCTYPE html>
<html>
<head>
    <style>
        body{background: #ccc}
        div{
            width: 100px;
            height: 100px;
            background: #fff;
            border: 1px solid #000000;
            position: relative;

        }
        div:before, div:after{
            content: ""; 
            width: 0px;
            height: 0px;
            position: absolute;
            bottom: -20px;
            left: 40px; 
            border: 10px solid transparent;
            border-top-color: #fff;
        }
        div:before{
            bottom: -21px;
            border: 10px solid transparent;
            border-top-color: #000000;
        }
    </style>   
</head>
<body>
    <div></div>
</body>
</html>

效果如图:
使用CSS伪类实现三角

[原发布时间: 2016-03-27] JS判断字符串长度(英文占1个字符,中文汉字占2个字符)

计算字符串长度(英文占1个字符,中文汉字占2个字符)

方法一:

String.prototype.gblen = function() {    
    var len = 0;    
    for (var i=0; i<this.length; i++) {    
        if (this.charCodeAt(i)>127 || this.charCodeAt(i)==94) {    
             len += 2;    
         } else {    
             len ++;    
         }    
     }    
    return len;    
} 

方法二:

function strlen(str){  
    var len = 0;  
    for (var i=0; i<str.length; i++) {   
     var c = str.charCodeAt(i);   
    //单字节加1   
     if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c && c<=0xff9f)) {   
       len++;   
     }   
     else {   
      len+=2;   
     }   
    }   
    return len;  
}  

方法三:

var jmz = {};  
jmz.GetLength = function(str) {  
    ///<summary>获得字符串实际长度,中文2,英文1</summary>  
    ///<param name="str">要获得长度的字符串</param>  
    var realLength = 0, len = str.length, charCode = -1;  
    for (var i = 0; i < len; i++) {  
        charCode = str.charCodeAt(i);  
        if (charCode >= 0 && charCode <= 128) realLength += 1;  
        else realLength += 2;  
    }  
    return realLength;  
};  

方法四:

var l = str.length;   
var blen = 0;   
for(i=0; i<l; i++) {   
    if ((str.charCodeAt(i) & 0xff00) != 0) {   
        blen ++;   
    }   
    blen ++;   
}  

方法五:

把双字节的替换成两个单字节的然后再获得长度

getBLen = function(str) {  
    if (str == null) return 0;  
    if (typeof str != "string"){  
        str += "";  
    }  
    return str.replace(/[^\x00-\xff]/g,"01").length;  
}  

[原发布时间: 2016-02-18] CSS3的毛玻璃模糊效果

说说前端如何毛玻璃模糊效果

毛玻璃模糊效果

CSS3 blur滤镜实现

css文件

.blur {   
    -webkit-filter: blur(10px); /* Chrome, Opera */
       -moz-filter: blur(10px);
        -ms-filter: blur(10px);   
            filter: blur(10px);   
}

HTML代码:

<img src="test.jpg" />
<img src="test.jpg" class="blur" />

利用svg处理兼容

需要注意目前火狐不支持,其他些浏览器,如FireFox到目前还没有支持CSS3 filter. 当然,要实现(比方说)FireFox 24浏览器上照片变模糊的效果,也是可以的。可以使用SVG的模糊滤镜。
新建文命名为blur.svg的SVG文件:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xmlns:ev="http://www.w3.org/2001/xml-events"    
     baseProfile="full"> 
    <defs>
        <filter id="blur">
            <feGaussianBlur stdDeviation="10" />
        </filter>
    </defs>
</svg>

如下CSS调用代码:

.blur {
    filter: url(blur.svg#blur); /* FireFox, Chrome, Opera */
}

处理低版本IE效果

.blur { 
    filter:
progid:DXImageTransform.Microsoft.Blur(PixelRadius=10, MakeShadow=false); /* IE6~IE9 */
}

完整的css代码

.blur { 
    filter: url(blur.svg#blur); /* FireFox, Chrome, Opera */    
    -webkit-filter: blur(10px); /* Chrome, Opera */
       -moz-filter: blur(10px);
        -ms-filter: blur(10px);    
            filter: blur(10px);
    filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius=10, MakeShadow=false); /* IE6~IE9 */
}

[原发布时间: 2016-03-05] WEB开发者应该具备的6大技能

WEB开发本身涵盖了许多领域的许多技术,那么,有哪些是WEB开发者必备的技能呢?这是一个Quora上用户提出的问题,其中Ellyse Taylor的回答获得了1900+的赞同。

可能很多人对下面这个列表中的大部分内容都已经了解了,但其中必定有一些是你之前没有看到过,或者没有完全理解的,甚至有些你可能从来没听说过。

1. 界面和用户体验

  • 注意,浏览器的实现标准是不一致的,请确保你的网站能够兼容所有主流的浏览器。最少需要测试的有 Gecko 引擎(Firefox),WebKit引擎(Safari以及一些手机浏览器),Chrome,你所要支持的 IE 浏览器,以及 Opera。此外,你还需要了解不同系统下,浏览器是如何渲染网页的。
  • 考虑一下人们不使用主流浏览器的情况,如手机,屏幕阅读器和搜索引擎。一些可用的辅助信息:WAI 和 Section508,移动开发:MobiForge。
  • 阶段:如何在不影响用户的情况下部署更新。有一个或多个可以用来改变架构、代码或全部内容,并确保它们在可控范围内实现部署的测试或临时环境。有一种自动化的方式把更新部署到线上网站。最有效的实现方式是结合使用版本控制系统(CVS、Subversion等)和自动构建机制(Ant、NAnt等)。
  • 不要直接向用户显示不友好的错误信息。
  • 不要用纯文本的方式显示用户的电子邮件,因为他们可能会被垃圾邮件烦到死。
  • 为用户生成的链接添加 rel=”nofollow” 属性,以避免垃圾邮件。
  • 为你的网站建立周全的限制–这条也同时属于安全方面。
  • 学习如何进一步的提高。
  • POST 提交成功后进行重定向,以免刷新造成重复提交。
  • 别忘了考虑无障碍访问。这总是不错的,在某些情况下,这甚至是法律要求的。 WAI-ARIA 和 WCAG 2 里都有关于这方面很好的资源。
  • 不要让我思考。

2. 安全

  • OWASP开发指南几乎覆盖了网站安全所有的内容。
  • 了解注入,尤其是 SQL注入,并学会如何阻止它。
  • 永远不要相信用户的输入,以及其他任何请求(包括Cookies和隐藏域的值)。
  • 使用盐值(salt)哈希密码,并对不同的行使用不同的盐值,防止攻击。使用哈希算法如 bcrypt 或 scrypt(更安全,但比较新)(1, 2)来存储密码。(如何安全的存储密码)。NIST也允许使用PBKDF2来加密密码。避免直接使用 MD5 和 SHA 等算法。
  • 不要企图拿出自己喜欢的认证系统。这是很容易出错的,并且是不可测的,甚至直到你被攻击了你才知道。
  • 了解信用卡处理规则。(也可查看该问题)
  • 在登录页和任何需要输入敏感数据的页面使用SSL/HTTPS。
  • 防止 session 被劫持。
  • 避免跨站脚本(XSS)。
  • 避免点击劫持。
  • 保持系统更新到最新的补丁。
  • 确保数据库连接信息的安全。
  • 让自己了解最新的攻击技术和会影响你平台的漏洞。
  • 阅读谷歌浏览器安全手册。
  • 阅读WEB应用黑客手册。
  • 考虑最小特权原则,尽量使用非root用户运行服务器(以tomcat为例)。

3. 性能

  • 如果有必要的话,实现缓存,请正确理解和使用HTTP缓存。
  • 优化图片。不要使用20K的图片作为平铺背景。
  • 学习如何 gzip/deflate 内容(deflate效果更好)。
  • 合并样式表与脚本文件以减小浏览器链接数,同时提高 gzip 的压缩能力。
  • 浏览雅虎性能卓越的网站,以及大量的指南,其中包含提升前端性能和YSlow工具(需要安装Firefox, Safari, Chrome 或 Opera)。此外,Google page speed(浏览器扩展)也是一个性能分析工具,它同时可以优化你的图片。
  • 对于小的如工具栏图片,使用CSS Image Sprites(参考最小化HTTP请求)。
  • 访问量大的网站应该考虑跨域拆分组件。
  • 静态内容(如图片、CSS、JavaScript及不需要访问cookie的内容)应该放在一个单独的域下,因为域及其子域的每一个请求都会发送cookie。这里是使用内容分发网络(CDN)的一个很好的选择。
  • 减少浏览器渲染页面所需的HTTP请求的总数量。
  • 利用Google Closure Compiler及其他压缩JS的工具。
  • 确保网站根目录下有一个favicon.ico文件,即使在HTML中并没有提到它,浏览器也会自动加载它。如果你没有 /favicon.ico ,就会返回很多404错误,消耗服务器带宽。

4. SEO (Search Engine Optimization) 搜索引擎优化

  • 使用“搜索引擎友好”的URL,如http://example.com/pages/45-article-title而不是http://ofexample.com/index.php?page=45。
  • 在动态内容中,把 # 改成 #! ,然后在服务器端使用$_REQUEST["escaped_fragment"]。换句话说 ./#!page=1变成了./?escaped_fragments=page=1。此外,对于使用FF.b4或Chromium的用户,history.pushState({“foo”:“bar”}, “About”, “./?page=1″); 是一个非常棒的命令。因此,即使地址栏已经改变了,页面也不会刷新。
  • 不要使用“点击这里”这样的链接。你是在浪费一个搜索引擎优化的机会,而且它让使用屏幕阅读器人们更难阅读。
  • 有一个XML网站地图,最好在默认位置/sitemap.xml。
  • 当有多个URL指向同一个内容的时候,使用<link rel=”canonical” … />,这个问题可以通过Google Webmaster Tools来解决。
  • 使用Google Webmaster Tools和Bing Webmaster Tools。
  • 安装Google Analytics或者其他开源分析工具如:Piwik。
  • 了解robots.txt及搜索引擎蜘蛛是如果工作的。
  • 使用重定向(301)www.example.com到example.com(或者反过来),防止它们平分谷歌网站排名。 要知道有badly-behaved蜘蛛的存在。
  • 如果你的网站有非文本内容,Tim Farley的回答中有一些非常有用的信息。

5. 技术

  • 理解HTTP以及GET、POST、session、cookie以及“无状态”的意思。
  • 撰写XHTML/HTML和CSS要遵循W3C规范,并确保它们通过校验。这样做的目的是为了避免浏览器的怪癖模式,并且这使得非标准浏览器如屏幕阅读器和移动设备更加容易实现。
  • 理解浏览器是如何处理JavaScript 的。
  • 理解JavaScript 、样式表、以及页面使用的其他资源是如何加载的,并考虑它们对感知性能的影响。现在普遍认同的一种做法是把除分析代码等以外的脚本文件放在页面底部。
  • 了解JavaScript 沙箱是如何工作的,特别是当你想使用 iframe 的时候。
  • 需要注意到,JavaScript是可以被禁用的,因此AJAX只是一个扩展,而不是基准。虽然大部分用户并没有禁用它,但记住,NoScript正在变得越来越流行。并且,谷歌在索引你的网站时也不会运行JavaScript。
  • 学习301和302重定向之间的不同。
  • 尽可能多地了解你的部署平台。
  • 考虑使用Reset Style Sheet或normalize.css。
  • 考虑使用JavaScript框架(如jQuery, MooTools, Prototype, Dojo 或 YUI 3),这可以避免很多使用JavaScript操作DOM时的差异。
  • 在考虑感知性能和框架的同时,考虑使用服务,如Google Libraries API,来加载框架,这样浏览器可以使用已经缓存的框架而不是从你的网站上下载。
  • 不要重复造轮子。在做任何事情之前,先搜索相关的组件或者实例。99%的可能别人已经实现了并发布出了开源的代码。
  • 在确定需求之前,尽量不要使用超过20个的库,这是非常不利的。特别是客户端WEB,保存轻便、快速、灵活是最重要的。

6. BUG修复

  • 要了解你花费20%的时间写代码而花费80%的时间来维护,因此写代码时一定注意。
  • 建立一个好的错误报告解决方案。
  • 建立一个别人可以提建议和批评的系统。
  • 为未来的支持人员和维护人员建立良好的文档。
  • 经常备份!Ed Lucas的回答中有一些建议。有一个恢复策略,而不只是一个备份策略。
  • 使用版本控制系统,如Subversion、Mercurial或Git。
  • 不要忘记验收测试。Selenium等框架可以帮到你。
  • 请确保您有足够的日志记录的地方,可以使用框架如log4j, log4net 或 log4r。当网站出现问题的时候,你需要能够找到问题所在。
  • 日志要记录已处理异常和未处理异常。分析日志输出,因为它会显示出你网站的关键问题。

这里有些省略的东西并不是因为它们没用,而是因为它们过于详细或者超出了范围,或者说的太远了。当然,上面的内容可能也有一些遗漏或者错误。

[原发布时间: 2016-03-01] JS动态修改微信浏览器中的title

平时使用JS修改title,直接document.title=新标题就好了
这样在安卓的微信浏览器是正常运行,可在IOS中这样的确不起作用。
这是因为微信浏览器的title在页面加载完成后就确定了,因此如果光使用document.title来修改,不会有效果。
所以这里使用了黑科技。

我们的原理是设置一个ifame然后我们再加载一下就可以实现了.

在微信浏览器中使用如下代码来动态修改浏览器上的title标题:

var $body = $('body');
document.title = '这里是要修改成的新标题';
var $iframe = $('<iframe src="/favicon.ico"></iframe>');
$iframe.on('load',function() {
    setTimeout(function() {
        $iframe.off('load').remove();
    }, 0);
}).appendTo($body);

由于微信浏览器只在页面首次加载时初始化了标题title,之后就没有再监听 ** window.title ** 的change事件。所以这里修改了title后,立即创建一个请求,加载一个空的iframe,由于加载后立即就移除,也不会对页面造成影响,但这样微信浏览器上的title便刷新了。

[原发布时间: 2016-03-02] 通过正则判断是否为邮箱格式

//var email = document.getElementById('emailname').value;
var email = $('#emailname').val();
var reEmail=/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
//var reEmail= /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
var isok= reg.test(email );
if (!isok) {
    alert('邮箱格式不正确,请重新输入!');
    $('#emailname').focus();
    return false;
}
解释: 
    开始的 ^ 和 结尾的 $ 表示 匹配输入字符串的开始位置和结尾位置  
    \w 匹配包括下划线的任何单词字符。等价于 A-Z  a-z 0-9 和 _ 的字符  
    [-+.] 字符集合。匹配所包含三个字符中的任意一个字符  
    + 匹配前面的子表达式至少一次,就是说他前面的字符 至少有 一个  
    * 匹配前面的子表达式零次或多次  
    ( ) 当然是 匹配括号里面的字符啦  

** 整句的意思就是说:
邮箱地址 必须由 大小写字母 或 数字 或下划线开头,其后可以跟上任意的 \w字符 和 中划线 加号 英文句号 @ 跟上任意的 \w字符 和 中划线 加号 英文句号.跟上任意的 \w字符 和 中划线 加号 英文句号 **

[原发布时间: 2016-04-14] js函数前面的加号、叹号

+function(){}();

这里的加号,也可以替换成!,~等其他一元操作符,其效果相当于:

(function() { console.log("Foo!"); })();
// or
(function() { console.log("Foo!"); }());

如果没有这个加号的话,解析器会认为function是一个函数声明的开始,而后面()将会导致语法错误。在function前面加上+号时,就变成了一个函数表达式,而函数表达式后面又添加了一个()就变成了一个立即执行的函数了。

[原发布时间: 2016-02-17] 让多说给你的Hexo站点添加最近访客

下面简单介绍如何通过多说给你的Hexo站点添加最近访客。

留言访客

引入多说通用JS代码(3.0以前)

注意修改您的多说二级域名,每个页面只需引用一次,也就是说你的页面本来就有多说评论的话,就无需再次添加该代码了。正在使用next主题的站长可以参考我的NexT主题创建“留言”页面实现指定某些页面添加多说评论系统。

<!--多说js加载开始,一个页面只需要加载一次,注意修改您的多说二级域名 -->
<script type="text/javascript">
var duoshuoQuery = {short_name:"您的多说二级域名"};
(function() {
    var ds = document.createElement('script');
    ds.type = 'text/javascript';ds.async = true;
    ds.src = 'http://static.duoshuo.com/embed.js';
    ds.charset = 'UTF-8';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ds);
})();
</script>
<!--多说js加载结束,一个页面只需要加载一次,注意修改您的多说二级域名 -->

修改md文件

往你想添加的页面增加下面的一小段代码即可。

<div class="ds-recent-visitors" data-num-items="28" data-avatar-size="42" id="ds-recent-visitors"></div>

其中

class="ds-recent-visitors"  //指定显示最近访客容器
data-num-items="28" //显示最近访客的数量
data-avatar-size="42"   //显示最近访客头像尺寸大小
id="ds-recent-visitors" //为了调节最近访客样式加的

我的hexo站点是通过直接生成了guestbook的page,然后直接在/guestbook/目录下的index.md添加了上面那段代码实现的。
guestbook目录下的index.md代码

title: 留言
date: 2016-02-15 19:16:16
type: guestbook
---
<blockquote class="blockquote-center">留下你的话语,带走我的问候,欢迎大家没事踩踩。</blockquote>
<br/>
> 最近访客

<div class="ds-recent-visitors" data-num-items="28" data-avatar-size="42" id="ds-recent-visitors"></div>

修改hexo最近访客样式

通过多说后台管理>设置>基本设置>自定义CSS修改最近访客css样式

最近访客竖着排,改成排成一列

#ds-recent-visitors .ds-avatar {float:left}

最近访客头像样式css和评论样式统一

#ds-reset .ds-avatar img,#ds-recent-visitors .ds-avatar img{这里是你定义的多说头像样式css}

最近访客头像样式css和评论样式css分开设置

#ds-reset .ds-avatar img{这里是自定义多说评论头像样式}
#ds-recent-visitors .ds-avatar img{这里是自定义的多说最近访客头像样式css}

总结

我的整个多说自定义css,其中访客样式和评论样式统一

#ds-reset .ds-avatar img,
#ds-recent-visitors .ds-avatar img {
    width: 54px;
    height: 54px;     /*设置图像的长和宽,这里要根据自己的评论框情况更改*/
    border-radius: 27px;     /*设置图像圆角效果,在这里我直接设置了超过width/2的像素,即为圆形了*/
    -webkit-border-radius: 27px;     /*圆角效果:兼容webkit浏览器*/
    -moz-border-radius: 27px;
    -webkit-transition: 0.4s;
    -webkit-transition: -webkit-transform 0.4s ease-out;
    transition: transform 0.4s ease-out;     /*变化时间设置为0.4秒(变化动作即为下面的图像旋转360读)*/
    -moz-transition: -moz-transform 0.4s ease-out;
}

#ds-reset .ds-avatar img:hover,
#ds-recent-visitors .ds-avatar img:hover {
    transform: rotateZ(360deg);     /*图像旋转360度*/
    -webkit-transform: rotateZ(360deg);
    -moz-transform: rotateZ(360deg);
    opacity: 1;
}

#ds-thread #ds-reset .ds-textarea-wrapper textarea {
    background: url(http://ww4.sinaimg.cn/small/649a4735gw1et7gnhy5fej20zk0m8q3q.jpg) right no-repeat;
}

#ds-recent-visitors .ds-avatar {
    float: left
}
/*隐藏多说底部版权*/
#ds-thread #ds-reset .ds-powered-by {
    display: none;
}
#ds-recent-visitors .ds-avatar img{
    opacity: 0.4;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.