HTML

HTML5标准学习 – 文档结构

说起HTML的结构,很多人都能说得头头是道,一般来说答案可能是这样的: 一个DOCTYPE,一个<html>,里面有<head>和<body>元素。 这当然不能说是不正确的,但是如果问到一个最小的HTML源文件必须有哪一些东西的话,恐怕很少有人能正确地做出回答。 先来回答一下这个问题,一个最简的HTML5源码文件需要的内容如下: <!DOCTYPE html> 是的,就这样,一个字符不多,一个字符不少,除了大小写可任意变化外,其他的任何内容都是不能变动的。 那么究竟是怎么样的规则,

HTML

HTML5标准学习 – 简介

最近前端的群都蛮热闹的,但我发现多数讨论的是javascript和css相关的问题,仿佛大家在努力创建各种交互、样式的时候,忘却了这一切的基础 – HTML。 其实我很喜欢HTML,觉得这个语言远比XML来得有趣,其灵活、轻便远非极端规范的XML可以比拟。同时又因为HTML的作用范围极小,规定的标签有限等说不上优点还是缺点的特色,使得HTML有着自己的确定性。 本系列的前面很大一部分会以非常短小的篇幅,介绍HTML5中的一些基本概念,并且: 只关心HTML这个语言,其他的javascript或者css完全不会涉及。 只关注HTML,对XHTML会简要带过,但不会详细说明,这源于XHTML有着比HTML更严格的规范,对浏览器的解析而言,可以认为是HTML的一个子集。 主要参考了whatwg的官方文档,并对现有主流浏览器的兼容性进行了评估。 介绍的全是基本的概念,不会涉及文档解析、DOM树构建、脚本执行之类的实现细节。 在这之后,可能会提取部分与浏览器的运行相关的技术细节,如脚本的解析、

杂想

BUG平台应该是一个知识库

我很喜欢看各个产品的Bug追踪系统,比如jQuery的Bug Tracker,因为在Bug系统中总能发现一些非常细节的问题,补充自己的知识,慢慢地自己的代码的兼容性会有很大的提高。 但是,在各个Bug系统之中,包括现在公司使用的Trace系统,无一例外地存在一些让我不满意之处,其中最大的原因就是很多Bug系统仅仅是作为Bug的记录系统存在,而没有试图去让一个Bug成为一个知识的积累,让整个Bug系统变成一个丰富充实的知识库。这样的Bug系统,永远都只是提供一个简单的业务流程,不会变成干完人员、产品、甚至是整个团队的进步的天梯。 在我看来,一个Bug系统应该更加全面,管理Bug的生命周期的同时,也用于管理一个产品、团队的知识,更可以与周边系统合作,形成一个真正的集成式管理平台。 Bug的分类 现在的Bug系统,对Bug系统的分类通常有这么几种: 根据性质:Bug、Feature、Enhancement等。 根据危险程度:

性能

各浏览器对页面外部资源加载的策略

这个总结来源于一次优化的请求,最初某个页面的加载十分缓慢,load事件迟迟无法触发,因此希望可以通过对静态文件分域名等方式对页面的外部资源进行优化,拿得load事件尽可能早地触发。 于是我查看了页面的源码,并对外部资源进行了整理,基于下面2个理念画出了一个推测的瀑布图: 浏览器对同一个域只能并发2个HTTP请求 – 网上盛传已久。 javascript文件的加载会阻塞浏览器其他资源的加载 – 同样网上盛传已久。 然而,当我看到各浏览器中实际的瀑布图时,我知道自己又犯了一个简单的错误:太过相信所谓的权威和大众的声音,而没有更早地进行实践来检验理论的正确性…… 本篇文章就使用几种流行的浏览器,针对同一个页面的外部资源加载过程进行分析,推测各浏览器加载外部资源的策略、特征,并最后给予一定的比较和总结。 测试样例 测试的页面结构如下: head 1.css + 1.js body 1.jpg + 2.

JavaScript

引入Flash那些事

最近做的事和Flash打交道比较多,简单来说,就是要在第三方的页面引入一个Flash的广告,播放一会,让用户能够关闭。 起初总觉得,就引入一个Flash嘛,Adobe都给出了官方的使用方法,直接拿来用不就成了。顶多IE下不支持object元素的appendChild,大不了拼接字符串然后通过innerHTML来创建就好了。 但是真正做的时候,开始测试各个浏览器的时候,才发现情况远没有想的这么简单…… 关于如何引入Flash 这大概是最基本的问题,其他的一切问题都是基于Flash可以正确引入到DOM中这个前提的。 最先的方式自然是使用adobe给出的官方方式,即<object><embed /></object>的结构来嵌入一个Flash。根据各种资料,<embed>

JavaScript

记一次失败的jQuery优化尝试

我经常抱怨jQuery的DOM操作性能并不优秀,并且经常尝试用一些方法去进行优化,但是越是优化,越是沮丧地发现jQuery其实已经做得很好,从使用者的角度能够进行的优化实在有限(这并不意味着jQuery的性能是优秀的, 反之只能说它是一个相对封闭的库,无法从外部介入进行优化)。这篇文章就记录一次失败的优化经历。 优化思想 这一次优化的思想来自于数据库。在数据库优化的时候,我们常会说将大量的操作放在一个事务中一起提交,能有效提高效率。虽然对数据库不了解的我并不知道其原因,但是“事务”的思想却为我指明了方向(虽然是错的……)。 因此我尝试将“事务”这一概念引入到jQuery中,通过打开和提交事务,从外部对jQuery进行一些优化,其最重要的在于减少each函数的循环次数。 众所周知,jQuery的DOM操作,以get all, set first为标准,其中用于设置DOM属性/样式的操作,

JavaScript

单页系统前端MVC设计 – MVVM模式

在上一篇中,Action已经可以获取所有需要的数据,下一步就是将数据与视图中的控件树进行关联,使得View模块可以获取、修改数据,并通过与Action的进一步交互来完成整个业务逻辑。 MVVM模式 在介绍本文的ValueStack和ModelDescriptor这两个在整个框架中意义非凡的组件之前,需要先简单地介绍一下MVVM模式。 这个MVC框架引入了MVVM模式,MVVM模式的全称是Model-View-ViewModel模式。该模式顾名思义地有三个部分组成: Model:即数据,所有可持久化和不可持久化的,与业务有着关系的内容都可以被称为数据。Model的数据是扁平的,为了区别下面的ViewModel,这里可以称之为FlatModel。 例如,一个系统有用户,以及用户发表的文章,期间是1:n的关系,那么Model就存在两条数据。其一为user,其二为postList,两者之间虽然有着“从属”的关系,但是在FlatModel这样“扁平”的结构中,

JavaScript

单页系统前端MVC设计 – 获取数据

一个单页系统中,由于浏览器始终不能离开当前页面,从而无法利用服务器端的动态页面(ASP、JSP、PHP等)将数据与页面结合起来,数据与表现相比单独的页面请求分离得更为彻底。其中数据获取的部分,通常使用的是AJAX的技术,利用XMLHttpRequest向服务器请求数据。 我在很多篇文章中提到过,现有互联网的大部分应用是数据驱动的,数据是整个业务的核心和关键所在。在框架的执行过程中,Action同样需要数据才可以驱动整个界面的渲染及交互,因此当Action进入自身的执行流程时,第一件事就是将自己需要的所有数据获取过来。 Action流程 Action从execute开始,到renderView绘制视图,并在之后与视图进行交互,其执行流程如下所述: 调用execute函数开始流程。 调用prepareData函数,该函数中利用DataProxy组件获取数据。 当所有数据请求完成后,会调用buildModel函数,该函数通过ValueStack和ModelDescriptor两个组件,将第2步中获取的数据组装成为更加结构化、可用于视图中的控件树的模型。 完成了模型的组装后,调用getRoot函数,

JavaScript

单页系统前端MVC设计 – ActionMapping过程

上一篇讲到通过对外暴露LocationManager组件,提供接口进行redirect等操作,可以形成一个Request对象交给Controller(即调用Controller的process函数)。 本篇主要讲述Controller如何处理一个Request,包括通过Request查找到对应的Action,并准备好上下文对象,交进而进入到Action的执行流程中。 Request对象 类似服务器端的MVC框架,Request对象将提供对一次请求中所能接触到的所有内容的封装,其会包含以下内容: url、path、query属性,对应window.location的href、pathname和search属性,表示整个请求资源符或者其中的一部分。 getParameter(key)函数,获取query中某个键对应的值。 getSession(key)函数,获取Session或者Session中某个键对应的值。 getAppContext(key)函数,获取AppContext或者AppContext中某个键对应的值。 Session对象及AppContext对象 在服务器端,

JavaScript

单页系统前端MVC设计 – 入口

这一篇讲作为整个MVC框架的入口的LocationManager和HashListener组件。 LocationManager和HashListener作为框架最外层的组件,提供了整个框架的入口,其中HashListener依赖于LocationManager,并且通过LocationManager才能够进入到框架的运行流程中。 在设计中,HashListener将会被设计成一个内部的组件,不会对外暴露,其所有可能提供的接口都通过LocationManager作代理,以保证对外开放的对象尽可能地少,形成更简明的API。 LocationManager 在接触该组件之前,先解释一下hash这个名词的概念。 在Web中,浏览器的地址栏中的URL通常可以分成几个部分,比如有一个简单的地址: http://www.some-where.com/list.html?page=2&size=20#item-3 上面的URL就能分为下面几个部分: 橙色:protocol,此处表示使用http协议。

JavaScript

单页系统前端MVC设计 – 总览

这是近期可能会接触的设计,对应的需求大致是: 单页系统,所有与后端交互通过AJAX进行。 每个模块、功能有自己的独立界面。 不同模块、功能对应着不同的URL,要求能通过URL直接定位到相关的模块或功能上。 模块间相互穿插,一个功能可能会突然被另一个模块引入,比如放在Dialog中。 对于上面的需求,我们讨论认为,对应的设计至少要能满足以下条件: 基于URL的可导航性和可访问性。 能够非常清晰、明确地划分模块及功能,划分上模块、功能相互独立。 可以方便地引入另一模块或功能的相关界面、交互。 基于此,虽然有着非常严重的过渡设计的嫌疑,最后我们还是选择了MVC的模式。当然这也是因为已经有过一个项目使用类似的模式,并且需要重用其中的一部分功能。 这一篇主要介绍整个设计的总体结构,以及一个请求的流程,首先下面是总体设计的总览图: 图很复杂,组件很多,所以说这根本就是个过渡设计的东西。

JavaScript

一小段jQuery代码的分析与优化

今天刚回家,QQ群里就看到有人求助优化一段jQuery代码,简单看了一下,发现如果对jQuery这东西只停留在用的层面,而不知其具体实现的话,真的很容易用出问题来。这也是为什么近期我一直不怎么推崇用jQuery,这框架的API设定就有误导人们走上歧途之嫌。 需要优化的代码大致是这样的,也不方便直接把人家的代码复制过来,就大概地表达下意思: $.fn.beautifyTable = function(options) { // 定义默认配置项,再用options覆盖 return this.each(function() { var table = $(this), tbody = table.children('tbody'), tr = tbody.children('tr'), th

JavaScript

jQuery1.5的改进细节

jQuery 1.5 beta1出来了,从学习跟进上来说,这一次已经比较晚了(我竟然不知道1.5什么时候出的alpha,就这么beta了)。 这个1.5版本最大的更新是AJAX的完全重写,提供了更强的可扩展性。但是受制于精力和篇幅,对新的AJAX的分析还是放到下回,本篇先简单介绍一下细节方面的改进。 jQuery._Deferred和jQuery.Deferred 首先不得不说这两个新生事物,因为他们是作为基础设施存在,不把这两个东西讲明白了,有些问题根本没办法解释。 首先,jQuery.Deferred是jQuery._Deferred的增强版,因此对于这个问题,从jQuery._Deferred入手,就能说明一大半的问题。 什么是Deferred?从字面上看,我的第一反应是“

JavaScript

异步函数的依赖维护

写背景太麻烦了!总之随着AJAX理念的深入人心、随着一些纠结的问题在一个setTimeout之后奇迹般地被解决、随着未来更多的异步(WebWorker、WebSocket、message事件)功能的引入,编码人员变得必须熟悉“异步执行+回调”的编程模型。 但是随着项目、应用的规模扩展,复杂度上升,异步回调模型的理解和维护成本也使地逐渐攀升,毕竟人看东西总是从上往下的,没人喜欢看完一个函数的时候突然发现要去300行以后、甚至另一个文件里找一个回调函数。同时,为了更灵活地切分系统、更合理地设计接口,类似于“从多源取得数据并合并”之类的需求也被摆到了台面之上,这意味着多个异步调用之间开始存在依赖关系。在设计不那么理想的系统中,此类依赖关系也可能变得非常复杂,导致代码的逻辑不易看懂、回调函数四处传递等问题,维护性极剧下降。 为了处理以上提到的问题,就需要一个“

用户体验

从热力图上发现细节

百度统计的热力图功能上线了,cnbeta上一如既往的一片骂声,大概在那上回复的都不是什么真正的技术人员吧。 虽然不是同一个项目,但是统计小组为了这功能所付出的努力,也一直看在眼里,虽然热力图功能并不完善,甚至有着相当多的问题(仔细用一用就能发现了,和啥内部消息没有关系),但依旧不失为第三方统计中的一个创举。 确实热力图能反映很多细节和问题,但是发现这些也不是容易的事。本篇主要讲一讲我从百度统计官方空间给出的这张热力图中发现的一些内容。 这个应该是铁血社区的首页,某种程度上来说也是个门户了。接着针对热力图中我比较感兴趣的几个点说一说。 上方导航条 上方导航条每一项都是由4个汉字组成,从点击量来看,多数点击是落在第3个汉字上。 这大概算是网民的一种“中庸之道”的体现吧,不喜欢点头里,也不喜欢点尾部,倾向于中间偏后。 点击如此,是不是可以认为视觉上,一般第一时间也会落在第3个汉字上呢?如果是的话,那么导航条的设计就非常重要了,应当让第3个汉字起到突出全句的核心作用,

杂想

墙与非墙

有自己的房子也已经好几个月了,虽说现在去装修实在没意义,但是看着这个并不豪华甚至有些破旧的屋子,总免不了想一些日后的装修。 当一个人站在客厅的中央,客厅的墙上有着很大的镜子,让这个原本并不大的厅看上去无比宽广。就这样站在没有任何家具的客厅里,突然产生了一个奇妙的想法: 为什么,房子里要有墙呢? 我们不断遵从着社会的标准思想,将一个完整的房子用墙这样的东西隔成一个个小小的空间,客厅、餐厅、梳洗室、卧室……但是如果没有这样的分隔呢? 我的房子,会是一个完整的空间,没有任何的阻隔。在这一片空间之中,各种各样的家具用最合理的方式摆放,这一片用于休息,那一片用于进餐,一片与一片之间有着看上去非常适合的距离感,但是无论在哪里,我可以看到一切。 在这样的空间中,可以毫无阻碍地穿行。在一个角落享受热水的冲淋;在一个角落用餐之后享用甜点和悠闲的下午茶;在窗边看着太阳渐渐落下的金黄;

界面-数据-循环

数据,界面,循环 – 数据模型对界面的影响

上文介绍了数据建模的过程,最终得出一个含有Dataset、Data Item以及Operation的图状数据结构,其特点在于对Operation的关注,而不关注于常见的数据的属性、关系。 在数据建模中大量关注Operation及其之间的关系,就是为了让数据的模型可以有效地影响和指导界面的设计,从而形成“环”的两个部分的一条通路。 因此本文就介绍数据的模型如何指导界面的设计,以及从数据模型导出界面设计的一种方案。 导出跳转关系 在数据模型中,已经定义了针对各个Dataset以及Data Item的操作,同时也有了各个操作之间的关系。 还是使用上文中最后的数据模型: 首先可以假设,每一个操作,我们需要一个独立的界面模块来进行处理,比如针对上文的数据模型的定义,可以得出部分模块: 用户详情查看,User.R 文章列表,PostSet.L 文章详情查看,Post.

界面-数据-循环

数据,界面,循环 – 我是如何进行数据建模的

根据前言的介绍,设计、界面是一个相互影响的环,因此事实上从哪一点介入这个环并不重要,甚至完全取决与个人的喜好。对于个人而言,数据的建模方式也许可以说得更加精彩,因此就以“数据如何进行建模”作为这个环的切入点。 在小型应用的开发中,我是一个重数据而轻业务的人,也许很多注重领域业务的人会对此嗤之以鼻,但这确实是我经过不少项目之后的切身体会,并且也有一套自己的说法,具体的内容希望日后有机会可以写成博文进一步交流。 而在这里可以先不管业务、逻辑是否重要,事实上对于任何一个项目,数据的建模都是不可少的环节。在数据建模的过程中,我始终遵从一个原则:“数据的最终目的是与用户交互”,因此我对数据的建模是站在“交互”的角度出发的。 基本概念 首先,对于数据建模这一环节,会有几个下文中频繁使用的概念: Dataset:数据集,指一类数据的所有个体的集合。

界面-数据-循环

数据,界面,循环 – 前言

这会是一个系列文章,主要讲述在小型Web站点的设计与开发过程中,数据与界面之间如何相辅相承、相互影响。其中绝大部分内容(超过95%)来自于个人的观点,不尽正确,甚至可能和现有业界的部分观点存在着冲突和矛盾。 在我看来,对于一个小型的Web站点或者应用而言,界面是大门,而数据是核心,现有互联网上90%以上的小型Web应用都是以数据为驱动的。在这一类的应用中,数据与界面之间趋于一种不可隔离的状态,其主要体现在以下两点: 界面的作用是展现、修改数据,很少存在与数据无关的重业务型的界面。 任何数据,最终都需要通过界面才可以与用户进行交互,独立的数据没有太多意义。 因为数据与界面间紧密的关系,往往对于一个应用的设计,会采用两种方案进行设计: 自顶向下的设计方式,首先导出界面的框架,进而产生设计原型、交互原型,最终从界面上提取数据及数据间的关系,进而产生数据模型。

JavaScript

查找最近的共有祖先元素

司徒正美给出的题,也尝试着写一下。先来看概念,首先DOM是一棵树,其根节点是Document,大致可以用下图来表示: 所谓“最近的共有祖先元素”,是指给定一系列元素,找出在树中深度最大的,但同时为所有这些元素的祖先元素的元素。 比如上图中,I和G的结果为C,G和H的结果为A,D和E的结果为html,C和B的结果为html等。 测试驱动 对于偏逻辑的题,并没有十足的把握函数是正确的,因此还是先构造测试的用命,力求让函数通过测试。 本次就以上图的结构作为DOM结构,A表示body,B表示head,其他节点均使用div元素,同时以上文中所说的作为测试的输入和输出,先构造一下测试: function test() { var result; result = find(

JavaScript

预加载资源研究

什么是预加载 所谓预加载,就是通过一定的编程方法,使浏览器在空闲的时候,在后台通过HTTP请求访问某些资源。当用户在一段时间后真正使用这些资源的时候,相比一个完整的(返回200)的请求,可以更快地获得这些资源(返回304或者直接命中浏览器缓存)。 预加载在部分情况下有着十分重要的意义,特别是当确定某些资源用户在短时间内会使用,如分页列表的上一页和下一页、以及一些常用的LOGO之类的图片等。 预加载资源可能的方式 预加载的原理就是想办法发送一个HTTP请求,对响应的缓存等都由浏览器完成,因此一切有可能读取远程资源的方案都可以成为预加载资源的方案,大致有以下几类: 常规方式 使用<script>标签:<script type="other/prefetch"