• 【原译】解开面条代码: 怎样书写可维护JavaScript

      [译者注]:这篇文章结合作者自己的经历确实写的很到位,大部分内容感同身受。同时作者很有条理的告诉我们应该怎样去思考解决问题。推荐给大家~   几乎每个开发者都有接手过维护遗留项目的经历,或者说是一个旧的项目想继续维护起来。通常第一反应是抛开它们代码规范基础,按自己的意思去写。这样代码会很乱,不可理解,并且别人可能要花费好几天去读懂代码。但是,如果结合正确的规划、分析、和一个好的工作流,那就有可能把一个面条式的代码仓库整理成一个整洁、有组织并易扩展的一份项目代码。   我曾经不得不接手并整理很多的项目。但还没有很多开始就很乱的。但实际上,最近就遇到了一个这样的情况。虽然我已经学会了关于JavaScript代码组织的很多知识,最重要的是,在前一个项目开发维护中几乎疯掉。在这篇文章中我想分享下一些我的步骤和我的经验。 一、分析项目   最开始的一步是看一下到底怎么回事。如果是个网站,点击网站所有的功能:打开对话框、发送表单等等。做这些的同时,打开开发者工具,看下是否报错或输出日志。如果是个nodejs项目,打开命令行接口过一下api,最好的情况是项目有一个入口(例如main.js,index.js,app.js),通过入口能将所有的模块初始化;或者最坏的情况下,也要找到每个业务逻辑的位置。   找出使用的工具。jquery?React?Express?列出需要了解一些一切重要的东西。如果所在项目使用angular2写的,而你还没有使用过,直接去看文档先有个基本的了解。总之需要找下最好的开始方案。 在更高的层次上看项目   要知道技术是一个好的开始,但是为了有一个真实的感觉和理解,是时候研究下单元测试了。单元测试是用来测试功能和代码的方法是否按预期调用的一种方式。相比阅读代码和运行代码,单元测试能更深入的帮你了解代码。如果在你的项目中还没有单元测试,别急,我们接着往下看。 二、创建一个基准   这些都是关于代码一致性的内容。现在你已经了解了项目中使用的所有工具集,你知道了代码的结构和逻辑功能的位置,是时候建立一个基准了。我建议添加一个1editorconfig 文件来保证代码在不同的编辑器、ide或不同的开发者之间的编写风格一致。 正确的缩进   这是一个饱受争议的问题(跟战争一样),代码中使用空格还是tab,其实这不重要。如果之前代码用的空格,那么使用空格,如果使用tab,继续使用。如果代码中都使用到了,那么是时候决定使用哪个了。讨论的观点是好的,但是一个好的项目目的是必须保证所有的开发者能在一起和谐的工作。   为什么这很重要。因为每个人都有使用自己编辑器或使用ide的方式。举例来说,我是code folding的追捧者。没有这些特性,我几乎在一个文件里面迷失。如果缩进不是一样的,那么代码会看起来很乱。所以,们每次我打开一个文件,在我开始工作之前必须修复缩进的问题。这很浪费时间。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20// While this is valid JavaScript, the block can't // be properly folded due to its...


  • 【原译】javascript中的错误处理

    【原译】javascript中的正确错误处理   A Guide to Proper Error Handling in JavaScript   这是关于JavaScript中异常处理的故事。如果你相信墨菲定律,那么任何事情都可能出错,不,一定会出错!这篇文章中我们来看下JavaScript中的出错处理。文章会覆盖异常处理使用的正反例,然后看下ajax的异步处理。   JavaScript的事件驱动机制让JavaScript更加丰富,浏览器好比就是一个事件驱动的机器,错误也是一种事件。当一个错误发生时,一个事件就在某个点抛出。理论上,有人会说错误是Javascript中的简单事件。如果你觉得是这样,那你就要好好去看看了。另外这篇文章只关注浏览器端的JavaScript的情况。   这篇文章将在《Exceptional Exception Handling in JavaScript》这篇文章的概念基础上进行解释。解释起来就是,当发生错误时,JavaScript会去调用栈检查异常事件。如果你对此不熟悉建议先去看看基础的东西。我们的目的是探索处理异常的必要性,接下来你会看到一个 1try...catch 块语句,你要认真思考。 例子   例子的代码在github上,而且最终展示成这样:   所有的按钮点击是都会触发”炸弹”,这个炸弹模拟了一个抛出的 1TypeError 异常。下面是这个模块单元测试的定义: 1 2 3 4function error() { var foo = {}; return foo.bar(); }   开始时,这个函数定义了一个空的对象1foo ,注意 1bar() 没有在任何地方定义,我们用一个测试用例来看下它是如何引爆炸弹的。 1 2 3it('throws a TypeError', function () { should.throws(target, TypeError);...


  • 基于koa+fis3+swig前后端isomorphic同构实现

    基于koa+fis3+swig前后端isomorphic类同构实现   (认真把这篇文章看完,保证你会学到很多,如果没学到请联系作者或直接报警)   随着前端技术的不断变革,前端从后台吐页面 -> 前端MVC -> mvvm、react -> node直出 ->同构跨端的大致发展方向(后面我也讲下前端的跨终端实现),前端正在向着模块化、高效性、跨端性扩展。过渡完mvvm、react和node直出的阶段,前端工程师们又开始在通往后台同构的道路上探索。而且也出现了一些列可能的方案,例如使用mvc、mvvm或react在服务端做实现,无论如何。但是我们不得面临一系列问题。同构的目的?同构的核心?同构的代价?同构的优势? 一、同构的三个问题   我们先来看下这三个问题。 同构的目的   首先说下目前比较主流的web前后端分离方案:这种方案将web站点分为前端和后台,前端通过拉取后台数据的到页面再通过js模板渲染到页面上。几个主要问题,一是页面显示需要等后台请求(cgi等)返回来才能渲染,二是seo怎么办,同时也承受开发联调效率的考研。   所以node直出的方案在阿里、腾讯等大的前端团队里陆续被使用起来,思路是通过node直出首屏内容和关键性seo信息解决了上述问题。   但是问题是我们无法全部直出页面所有的内容,通常因为太大,所以前端仍然需要维护原有的前端代码。更多情况下,同一个站点中,我们更希望的是在某些场景下使用前端渲染,另一些情况下使用后端直出(例如,希望hybridapp在没有离线包的第一次直出,后面不需要下载静态文件时使用前端拉取渲染的方式,或者在高级的浏览器下使用http2前端渲染,低端浏览器上则使用直出),结果我们不得不维护两套不同的前后台代码,尽管可能都是用js写的。所以同构希望解决的是维护前后端维护两套代码的问题。 同构的核心   同构希望做的事情是只开发一套项目代码,既可以实现前端的渲染也可以做后台的直出。为什么可以这样做呢?因为后台直出页面在后端生成,实现的方式也是通过数据加上模板编译的方式生成,前端渲染和后台直出的模式生成dom的区别只在于数据和模板的渲染发生在什么时候。 同构的代价   同构的目的是为了统一前后台的方案,自然也会牵扯到前后端的适应性修改。例如前端的数据渲染如何与后台直出保持一致、后台如何处理异步的问题、在原有业务上的实现代价、和原有前端框架的的冲突性等等。如果考虑到这些问题,同构改造实现的代价就会很大,毕竟它是综合了两个开发人员的工作量。 同构的优势   同构的网站应该具有一些优势:1、可以根据用户需要方便的选择前端渲染还是后台支持;2、开发者真的只需要维护一套代码,当然这个是不严谨的,后台多出的工作是配置路由和数据接口编写,但和前端dom相关的指维护一套;3、前端的模块化开发和后台所有模块是共享的;4、可以避免前后端工程师的联调沟通成本,但整体成本会比单个人开发大;4、开发构建调试系统完善。 二、可能的解决方案 reactjs   这个被讨论的比较火。但事实上,目前直接使用react都比较困难,而react的应用现在就少,而且也没见过大型应用使用,所以同构的价值不大,其实对于此实现方案在开发时的配置依然比较多。不过技术上react同构是一个可行度很高的方案。   想多了解的话可以看下《isomorphic-reactjs》,其核心思路是使用renderToString将virtual dom直接转化成为html,因为virtual dom在前后端都可用。这样就实现了直出的转换。然而我想说的是,reactjs项目里面html和js混淆,模板语言生硬,渲染和事件绑定在一起,行为和结构层不分离只使用js来管理,本来对一般人来说技术学习成本高,项目大了很难管理,有可能带给我们至少两倍以上的成本。 mv*在后台直出方案   相比来说这个可行性稍大些。例如你只需要在服务器端实现一个mvvm的核心,通过自己实现dom分析器其来解析后端模板中的directives、filter、和事件bind就可以了,但是你要去做这个mvvm核心,而且如果你抛开主流的mvvm框架去做,而且要和前端使用的mvvm框架解析一样,除非如果保证你写的框架足够优秀能,或者被别人接受。当然一个可行的方案是完全根据现有某个主流mvvm框架(例如vuejs、avalon等)的语法来在后端实现一个功能相同的解析插件,因为现有主流的mvvm是不能在node上解析模板的。   这样的话开发的代码就必须是使用mvvm的模板来写了。当然根据mvc框架来实现的原理类似,不过可以灵活些。之前我们做过类似的事情,实现了vuejs的一些基础的directive和filter解析,但是我们业务前端都没有很多人使用vuejs,做同构很像后端上的一厢情愿。最后放弃了。 核心的问题   无论是react还是mvvm来实现,其实我们要弄清楚同构需要做的最核心的一件事情是保证一个数据渲染机制(react是virtual to html、mvvm是view模板)在前后端都能正确解析。所以保证这件事情实现了问题是不是就简单了。使用react或mvvm只是说我们可以更好的做前端模块化管理。      大多情况下,我们更多推荐使用mvvm管理vm模板,因为这样就可以模板重用了,但是我们也不得不考虑实现后端mvvm解析模板的代价。但其实在tpl模板层面只是需要一个通用模板,一个能同时支持后台和前端模块化开发的模板。mustache、handlebar、jade、ejs、artTemplate、kissy?似乎有很多选择,但是他们要么都只能在一端 工作,要么功能较简单,都不能直接解决问题。但是这个问题必须得到解决。 三、实现同构要解决的问题   通过分析,所以整理下我们需要解决的几个问题: 前后端框架选择。主要包括前端主要框架和后端的web框架的选择。 模板渲染机制。实现前后端dom渲染的统一,这个比较重要,刚刚重点讨论过了。 构建打包。同一套代码,基于前后端场景打包完成后应该是不一样的,并且对于开发者来说需要有完整的模块化机制、打包体系、不同输出调试目录 渲染和直出区分。怎样决定是选择前端渲染的方式还是后台直出的方式 四、最终解决方案 4.1 前后端框架选择 后端框架 koa   基于现在的的node端发展趋势,koa相比经典express(其它的一些不主流框架这里就不比较了,大家也可以去了解)有了很多优势,koa自实现的generator特性能用来写没有callback的异步处理,而使用express需要配合bluebrid使用promise特性;koa...


  • 【原译】React vs Angular 2: 战争继续

    React vs Angular 2: 战争继续 【原译】:https://tech.evojam.com/2016/03/31/react-vs-angular2-the-fight-rages-on/   google的Angular和Facebook的React是现在最流行(但不是只有两个)的浏览器端应用开发工具,它们都是很优秀的解决方案。然而angular 2仍然在beta版中,Google的一部分工程师已经对它进行测试了。使用react开发的应用也很多,像instagram,netlfix,paypal等。  残忍的战争就要到来了。 第一滴血 已经有一篇”血腥“的文章《Angular 2 versus React》(作者:Cory House)来比较angular2与react,它体现了两者很多方面的亮点,第一次对决已经结束,但是大战才刚刚开始。(译者注:老外写个文章真的一定要这么夸张吗?哈哈~) 认清你的对手 作为开发者,选择angular还是react就像购买现成的电脑还是用现成的零件来组装电脑一样。 Cory House告诉我们: angular 2 React 压缩后764K 压缩后151k 独立的完整解决方案 简单的视图库 很多angular特定的语法 javascript语法 很好的一致性(和typescript) 基本语法有点混淆 使用html和js jsx语法 综合成熟稳定的框架 发展迅速的开源库 手动debug,缺少完全的支持 jsx-很好的开发体验 对web components友好 有可能支持web componnets 静态执行 jsx-动态执行 我想补充的是react有很多优秀的浏览器开发插件,然而并没有看到angular 2的。 竞技场   为了比较这些前端的技术,我做了一些TODO应用。为了使问题更加简单,我在两个应用中只使用了Redux core(受angular 2-introduction to Redux启发)。两个都是使用typescript开发的,所以比较起来比较清晰些。你可以对比下代码:...


  • web前端安全机制问题全解析

      web前端安全方面技术含有的东西较多,这里就来理一理web安全方面所涉及的一些问题。 一、xss与sql攻击 入门级的安全知识,攻击手段和防范方法这里略过,不过注意的是xss分存储型xss、反射型xss、mxss(dom xss),主要防范思路是检查验证要输入到页面上的内容是否安全。 二、csrf 入门级的安全知识,攻击手段和防范方法这里略过 三、请求劫持与HTTPS 3.1、请求劫持   请求劫持现在主要分为两种,DNS劫持与HTTP劫持: DNS劫持: DNS劫持就是通过劫持了DNS服务器,通过某些手段取得某域名的解析记录控制权,进而修改此域名的解析结果,导致对该域名的访问由原IP地址转入到修改后的指定IP,其结果就是对特定的网址不能访问或访问的是假网址,从而实现窃取资料或者破坏原有正常服务的目的。DNS劫持通过篡改DNS服务器上的数据返回给用户一个错误的查询结果来实现的。   DNS劫持症状:在某些地区的用户在成功连接宽带后,首次打开任何页面都指向ISP提供的“电信互联星空”、“网通黄页广告”等内容页面。还有就是曾经出现过用户访问Google域名的时候出现了百度的网站。这些都属于DNS劫持。 再说简单点,当你输入google.com这个网址的时候,你看到的网站却是百度的首页。 http劫持: 在用户的客户端与其要访问的服务器经过网络协议协调后,二者之间建立了一条专用的数据通道,用户端程序在系统中开放指定网络端口用于接收数据报文,服务器端将全部数据按指定网络协议规则进行分解打包,形成连续数据报文。   用户端接收到全部报文后,按照协议标准来解包组合获得完整的网络数据。其中传输过程中的每一个数据包都有特定的标签,表示其来源、携带的数据属性以及要到何处,所有的数据包经过网络路径中ISP的路由器传输接力后,最终到达目的地,也就是客户端。   HTTP劫持是在使用者与其目的网络服务所建立的专用数据通道中,监视特定数据信息,提示当满足设定的条件时,就会在正常的数据流中插入精心设计的网络数据报文,目的是让用户端程序解释“错误”的数据,并以弹出新窗口的形式在使用者界面展示宣传性广告或者直接显示某网站的内容。列入本地的fiddler为一种劫持 请求劫持唯一可行的预防方法就是尽量使用HTTPS协议访问。 3.1、公钥和私钥   什么是https,这里不再解释了,简单理解就是通过SSL(Secure Sockets Layer)层来加密http数据来进行安全传输。 那使用HTTPS是怎样进行安全数据传输的? 先看个有意思的问题:   A、B两个人分别在两个岛上,并且分别有一个箱子,一把锁,和打开这把锁的钥匙(A的钥匙打不开B手上的锁,B的钥匙也打不开A的锁)。此时A要跟B互通情报,此时需要借助C的船运输,C是一个不可靠的人,如果A直接把情报送给B或把情报放在箱子里给B,都可能会被C偷走;如果A把情报锁在箱子里,B没有打开A锁的钥匙无法获得情报内容。请问有什么办法可以尽可能快的让A和B互通情报。   这就是公钥和私钥的问题了,答案比较简单,也对应了公钥和私钥在https中的应用过程。   公钥(Public Key)与私钥(Private Key)是通过一种算法得到的一个密钥对(即一个公钥和一个私钥),公钥是密钥对中公开的部分,私钥则是非公开的部分。公钥通常用于加密会话密钥、验证数字签名,或加密可以用相应的私钥解密的数据。通过这种算法得到的密钥对能保证在世界范围内是唯一的。使用这个密钥对的时候,如果用其中一个密钥加密一段数据,必须用另一个密钥解密。比如用公钥加密数据就必须用私钥解密,如果用私钥加密也必须用公钥解密,否则解密将不会成功。—百度百科 3.2、Https的通信过程 整个通信过程如下图,以公钥加密方式为例: 1、客户端发送https请求,告诉服务器发将建立https连接 2、服务器将服务端生成的公钥返回给客户端,如果是第一次请求将告诉客户端需要验证链接 3、客户端接收到请求后’client finished’报文串通过获取到的服务器公钥加密发送给服务器,并将客户端生成的公钥也发送给服务器 4、服务器获取到加密的报文和客户端公钥,先使用服务器私钥解密报文,然后将报文通过客户端的公钥加密返回给客户端。 5、客户端通过私钥解密报文,判断是否为自己开始发送的报文串;如果正确,说明安全连接验证成功,将数据通过服务器公钥加密不断发送给服务器,服务器也不断解密获取报文,并通过客户端公钥加密返回给客户端验证。这样就建立了不断通信的连接。 3.3、Https协议头解析 以打开 https://github.com/ 的过程为例,请求通用头部如下 1 2 3 4 5Request URL:https://github.com/ouvens\n Request Method:GET Status...


  • Promise与异步

      接触过promise的的都知道它的应用场景和用途,Promise可以用来避免异步操作函数里的嵌套回调(callback hell)问题,因为解决异步最直接的方法是回调嵌套,将后一个的操作放在前一个操作的异步回调里,但如果操作多了,就会有很多层的嵌套。   Promise的实现方式比较多,有丰富的第三方库,ES6也已经原生支持了Promise,jquery中也有$.Deferred()等可以解决异步嵌套问题。 先给下Promise学术点的描述:   promise代表一个异步操作的执行返回状态,这个执行返回状态在promise对象创建时未必已知。它允许你为异步操作的成功或失败指定处理方法。 这使得异步方法可以像同步方法那样返回值:异步方法会返回一个包含了原返回状态的 promise 对象来替代原返回状态。 一、Promise的适用场景   Promise并非适用于所有的异步场景,例如事件的绑定,某个程度上Promise有点类似事件的监听回调,当触发某个操作时进行后面特定的逻辑。但Promise只能执行一次,且需要前面特定的操作执行完成才会进行下一步,一般分成功和失败两种场景,成功或失败后会立即执行响应函数。这就很适合判断一个比较耗时的操作是否最终执行成功的场景,就如我们通常理解的ajax网络请求、读取localstorage等操作。 二、Promise的表现   如果使用回调方法处理多个操作的异步场景,判断某个操作成功或失败的控制在于声明的匿名函数里面,使用Promise对象则可以重新定义异步执行的状态和控制逻辑。   promises的最重要的特点就是它把我们处理任何函数调用的成功或者失败的方式规范成了可预测的形式,特别是如果这个调用实际上的异步的。   Promise中有几个状态: pending: 初始状态。 非 fulfilled 或 rejected。 resolved: 成功的操作。也有的成为fulfilled 。 rejected: 失败的操作。   不同的Promise差异基本表现如下: 构造Promise对象 new Promise().resolve() 或者 new Pomise(function(resolve, reject) {}) 是否有 .done() .fail() .always() 等方法 是否有Promise.all()方法 是否有isRejected() isResolved() .then() return 结果链式的 三、几种规范的promise 2.1、Promise的Promise/A 规范和Promise/A+规范 先看下规范的地址: http://wiki.commonjs.org/wiki/Promises/A...


  • 2015-2016前端知识体系

    2015-2016前端知识体系 获取原图 一、框架与组件 bootstrap等UI框架设计与实现 伸缩布局:grid网格布局 基础UI样式:元素reset、按钮、图片、菜单、表单 组件UI样式:按钮组、字体图标、下拉菜单、输入框组、导航组、面包屑、分页、标签、轮播、弹出框、列表、多媒体、警告 响应式布局:布局、结构、样式、媒体、javascript响应式 第三方插件:插件管理 jQuery、zepto使用原理以及插件开发 支持amd、cmd、全局变量的模块化封装 $.fn.method = function(){} mvc/mvvm框架原理设计,vue/angular/avalon等 directive设计:html、text、class、html、attr、repeat、ref,可扩展 filter设计:bool、upperCase、lowerCase,可扩展 表达式设计:if-else等实现 viewmodel结构设计:例如数据,元素,方法的挂载与作用域 数据更变检测:函数触发,脏数据检测、对象hijacking polymer/angular2思想与设计思路 import技术 template和script引入方式 css样式命名空间隔离 简单复用第三方库 reactjs原理与使用 virtual dom单向数据绑定 js执行语法方式 UI由状态控制 commonJS/AMD/CMD 模块引入 模块定义 模块标识 UMD解决不同规范兼容性的问题,例如webpack封装 模块懒执行(CMD)与与预执行(AMD) loadJs模块化加载原理与实现 创建script标签,需要id映射到资源url onload加载模块队列判断 全部加载完成后触发 加载失败问题优化 requirejs、modjs、seajs polyfill、shim原理与实现 polyfill提供了开发者们希望浏览器原生提供支持的功能特性 shim将新的API引入到旧的环境中,且仅靠旧环境中已有的手段实现 virtual Dom、Incremental DOM 1.用js对象树表示dom树结构,根据该对象树构建dom树 2.状态改变时,重新构建对象,和旧的对象对比,记录两个对象树差异...


  • 下一代前端打包工具与tree-shaking

    一、js模块化打包概述   随着js模块化规范AMD、CMD、commonJs的出现,模块打包工具也在不断的出现和演变,依次出现了r.js、browserify和webpack,过去的2015年就是webpack大行其道的一年,又随着reactjs、es6的出现,webpack更是深入人心,因为其人性化的特点和友好性,确实给前端模块打包带来了极大的方便。   不过今天并不是重点讲webpack,而是rollup,要了解webpack,可以看我的另一篇文章:http://ouvens.github.io/frontend-build/2015/04/01/webpack-tool.html ,在讲rollup之前先来看看几种之前的前端打包方案。 二、js模块化打包方案   先区分下几个不同概念:包管理工具(package manager)、模块加载器(module loader),打包工具(bundler),包管理器指管理安装js模块的这类,例如npm、bower、jspm这些,模块加载器指向requirejs、modjs、seajs这些,模块加载器又主要遵循AMD、CMD、Commonjs三种规范,打包工具则指r.js、browserify、webpack这类。 1、r.js   在grunt结合requirejs的年代,r.js作为通用标配的打包工具普世存在,当然现在应该也有些团队在用。   r.js是requireJS的优化(Optimizer)工具,可以实现前端文件的压缩与合并,在requireJS异步按需加载的基础上进一步提供前端优化,减小前端文件大小、减少对服务器的文件请求。先来分析一个官网的例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 { appDir: '../www', baseUrl: 'js/lib', paths: { app: '../app'...


  • web前端响应式设计总结

    web前端响应式设计总结 一、响应式概述   响应式是指根据不同设备浏览器分辨率或尺寸来展示不同页面结构、行为、表现的设计方式。这里总结了响应式网站设计需要涉及到的相关的内容,有不正确的欢迎大家指正。谈到响应式网站,目前比较主流的做法是通过前端通过判断userAgent来做页面的302跳转。 那么问题来了,使用userAgent的问题: 依赖设备本身浏览器或设备特点,例如尺寸,屏幕分辨率等。 需要分配多个站点页面跳转适配浏览器。例如:ke.qq.com,m.ke.qq.com,来分别存放PC端和移动端的页面。 多了一次跳转,跳转之前的逻辑不能少,这样用户体验就慢了   当然我们也都知道像bootstrap这种ui框架也是响应式的,即写一份代码,在浏览器和移动端都能跑,然而事实上这些事远远不够的,而且在移动端为什么要加载那么多PC端的内容?   我们理解的是完整的响应式页面的设计不仅仅是通过屏幕尺寸来动态改变页面容器的宽度等,其实大部分人通常理解的都停留在这个方面。完整的响应式网站的实现其实需要考虑到以下这些问题:响应式布局、响应式html和css、响应式媒体、响应式javascript。   这些页面在移动端和PC端使用同一个页面(大家可以用chrome浏览器一下),这样就避免了多余的302跳转,另外页面布局、逻辑、图片等内容都通过不同浏览器来适应。下面具体讲下各个部分的实现所涉及的内容。 二、响应式布局   响应式布局是用来兼容浏览器分辨率,清晰度,横屏,竖屏的页面元素布局方式。一般使用栅格方式实现。时间思路有两种,一种是PC端优先,另一种是以移动优先,PC端作为一个扩展。由于移动端的资源比较优先,一般比较推荐从移动端扩展到PC端,这样就避免了在移动端加载多余的PC端内容。响应式布局主要可以结合几种实现方式: 1,移动端布局控制 使用 viewport标签在手机浏览器上控制布局控制不缩放等通用定义。 1 2<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1" /> <meta name="apple-mobile-web-app-status-bar-style" content="blank" /> 由于这些定义在移动端必须定义,这里还是需要定义,用到PC端也不影响,只是有些多余。 2,普通元素的栅格布局 对于普通的div布局,使用了通用简单的栅格布局,相信这个大家都知道原理: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16.row{ width: 100%; } .row .col-1 {...


  • 九种浏览器端缓存机制知多少

      浏览器缓存(Browser Caching)是浏览器端保存数据用于快速读取或避免重复资源请求的优化机制,有效的缓存使用可以避免重复的网络请求和浏览器快速地读取本地数据,整体上加速网页展示给用户。浏览器端缓存的机制种类较多,总体归纳为九种,这里详细分析下这九种缓存机制的原理和使用场景。打开浏览器的调试模式->resources左侧就有浏览器的8种缓存机制。    一、http缓存   http缓存是基于HTTP协议的浏览器文件级缓存机制。即针对文件的重复请求情况下,浏览器可以根据协议头判断从服务器端请求文件还是从本地读取文件,chrome控制台下的Frames即展示的是浏览器的http文件级缓存。以下是浏览器缓存的整个机制流程。主要是针对重复的http请求,在有缓存的情况下判断过程主要分3步: 判断expires,如果未过期,直接读取http缓存文件,不发http请求,否则进入下一步 判断是否含有etag,有则带上if-none-match发送请求,未修改返回304,修改返回200,否则进入下一步 判断是否含有last-modified,有则带上if-modified-since发送请求,无效返回200,有效返回304,否则直接向服务器请求    如果通过etag和last-modified判断,即使返回304有至少有一次http请求,只不过返回的是304的返回内容,而不是文件内容。所以合理设计实现expires参数可以减少较多的浏览器请求。 二、websql    websql这种方式只有较新的chrome浏览器支持,并以一个独立规范形式出现,主要有以下特点 Web Sql 数据库API 实际上不是HTML5规范的组成部分; 在HTML5之前就已经存在了,是单独的规范; 它是将数据以数据库的形式存储在客户端,根据需求去读取; 跟Storage的区别是: Storage和Cookie都是以键值对的形式存在的; Web Sql 更方便于检索,允许sql语句查询; 让浏览器实现小型数据库存储功能; 这个数据库是集成在浏览器里面的,目前主流浏览器基本都已支持;   websql API主要包含三个核心方法: openDatabase : 这个方法使用现有数据库或创建新数据库创建数据库对象。 transaction : 这个方法允许我们根据情况控制事务提交或回滚。 executeSql : 这个方法用于执行真实的SQL查询。    openDatabase方法可以打开已经存在的数据库,不存在则创建 1 var db = openDatabase('mydatabase', '2.0', 'my db', 2 * 1024);...

公众号

加我赏红包,哈哈哈

公众号

欢迎关注 极限前端 公众号