Giter Club home page Giter Club logo

blog's People

Contributors

bluers avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

anxingirl

blog's Issues

jquery find选择器在不同浏览器下的差异

初步测试,5000个节点的隐藏。

代码如下:

<!doctype html>

<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<meta charset="UTF-8"> 
<title>Document</title> 
    <script> var html = ""; for(var i=0;i<5000;i++){ var $m = '
  • '; html += $m; } $("body").find("ul").append(html); var time = new Date().getTime(); $("body").find("a").hide(); var endtime = new Date().getTime(); console.log("find cost" + (endtime-time));

    time = new Date().getTime();
    $("body a").hide();
    endtime = new Date().getTime();
    console.log("find cost" + (endtime-time));</script>

    IE7下find = 501ms,css =731ms

    IE11下find = 216ms , css = 32ms

    chrome下find = 683ms , css = 93ms

    firefox下 find = 285ms , css = 260ms

    safari find = 294ms , css= 105ms

    可能是因为IE7以下不存在css选择器原生方法,jquery针对此采用的sizzle引擎虽有所优化,但仍不及find方法。

    综合来说,现代浏览器(IE6,7除外)在CSS选择节点的执行效率上由于原生方法的优势均不同程度的有所提高。

    因此,在使用jquery时,若兼容在IE8以上的,则可以无脑采用css选择器,若考虑到IE6,7,则需要有针对性的使用find() (IE6,7)和 css选择器(IE8及以上)。

    IE9透明filter和opacity同时生效的解决办法 IE9 hack only

    问题:

      假设结构如下:

      

      若背景需要透明,通常会这么写:

      

    复制代码
    .wrapper{
    position:relative;
    width:100px;
    height:100px;
    }
    .cover{
    position:absolute;
    width:100%;
    height:100%;
    background-color:rgba(0,0,0,0.5);
    background-color:#000;
    filter:alpha(opacity=50);
    }
    复制代码
    在IE7,8,10以及chrome,firefox下正常。但在IE9下会产生双重透明的情况。见图

    原因:IE9识别filter,也识别rgba,所以导致了双重透明。而目前还没有只在IE9下生效的CSS HACK(如有请指正),除外。

    解决办法:

    复制代码
    .wrapper{
    position:relative;
    width:100px;
    height:100px;
    }
    .cover{
    position:absolute;
    width:100%;
    height:100%;
    background-color:rgba(0,0,0,0.5);
    background-color:#000;
    filter:alpha(opacity=50);
    }
    .cover:not(IE9Only){
    filter:alpha(opacity=100);
    }
    复制代码

    重点在于这个小精灵【:not(selector)】,selector随意

    解释:

      :not(selector)仅仅在IE9+下生效。IE9会自动忽略:not以及之后的内容并生效与当前元素,但IE10会产生实际作用。

    因此IE9下,生效的代码为

    复制代码
    .cover{
    position:absolute;
    width:100%;
    height:100%;
    background-color:rgba(0,0,0,0.5);
    background-color:#000;
    filter:alpha(opacity=50);
    }
    .cover{
    filter:alpha(opacity=100);
    }
    复制代码
    而IE10生效的代码为

    复制代码
    .cover{
    position:absolute;
    width:100%;
    height:100%;
    background-color:rgba(0,0,0,0.5);
    background-color:#000;
    filter:alpha(opacity=50);
    }
    复制代码
    从而很好的分辨出了IE9。这也可以作为IE9单独使用的一个css hack。

    CSS 伪类选择器:如何使用 CSS3 伪类

    CSS 伪类选择器:如何使用 CSS3 伪类

    任侠 2013-05-31 14:19 前端开发, 网站建设 抢沙发 11,114 views

    CSS3 是个好东西,但也很容易被她的变形(transform)和动画(其中许多特性因浏览器厂商而异)特性所迷惑,因而忘了那些已经被添加到标准规范中的最为基本的选择器。许多强大的新伪类选择器(最新的 W3C 规范中列出了 16 条)使得我们能够在新的标准范围内使用元素选择器。

    在探讨这些新的 CSS3 伪类之前,先简要回顾追溯一下这些在 Web 应用中常常被误解的 CSS 选择器。

    1. 伪类简史

    在 1996 年,当 CSS1 的规范完成后,一些伪类选择器已被囊括在内,其中许多你几乎每天都在使用。例如:

    • :link
    • :visited
    • :hover
    • :active

    这些状态都可以被应用到某个元素,通常是以 “a:伪类名”的形式。令人难以置信的是,在 W3C 于 1997 年 12 月发布 HTML4 规范之前,这些伪类已经被极为广泛地使用了。

    1.1 CSS2 来了

    于是 CSS2 来了。其建议规范在两年之后的 1998 年 5 月发布。随之令人兴奋的是添加了 :first-child 和 :lang() 新伪类。

    :lang

    有许多种表示文档语言类型的方法,如果你使用 HTML5,很可能会直接在 DOCTYPE 声明之后放置 语句(指定本地语种)。当然,你也可以使用 :lang(en) 伪类来修饰页面元素,对于语言动态变化的情况,这将非常有用。

    :first-child

    您可能已经在文档中使用 :first-child 属性。它通常用于添加或删除列表中第一个元素的上边框。奇怪的是,却没有 :last-child 这样的伪类与之对应。于是不得等到 CSS3 规范的对这两个兄弟伪类的支持。

    1.2 为何使用伪类?

    伪类如此实用的原因在于它们允许动态地设置内容样式。比如上面的 例子,我们能够描述当用户与链接进行交互时,链接该如何呈现样式。正如我们看到的,新的伪类允许我们根据元素在文档中的位置或状态,动态地设置其样式。

    16 个全新伪类已经成为 W3C 的 CSS 建议的一部分,它们被分成四组:结构伪类、UI 元素的状态伪类、一个目标(target)伪类和一个否定伪类。

    W3C 是 CSS 之家

    现在我们一起探究看看如何使用这 16 个新伪类选择器。我会使用和 W3C 相同的标识符来命名 CSS 类,比如 E 代表元素(element),n 表示数字(number),s 表示选择器(selector)。

    1.3 示例代码

    大部分新选择器都会给出参考示例,以便直观地看到代码呈现效果。这里会涉及一张适用于 iPhone 并且使用了 CSS3 伪类的表单。

    请注意,这张表单中大部分样式可以使用 id 和类(class)选择器设定。即便如此,仍然可以使用新伪类针为这个表单锦上添花。点击这里查看页面示例

    Awesome Widgets

    All the cool kids have got one

    Where do we send your receipt? Email Address Personal Details Title Mr Mrs Miss First Name Initial Surname Payment Details Name on card Card number Select Card Type Visa American Express MasterCard Expiry Date MM 01 02 03 04 05 06 07 08 09 10 11 12 / YYYY 11 12 13 14 15 16 17 18 19 Security code

    Would you like Insurance?

    Yes Please! No thanks Here I come!

    使用前和使用后的表单样式

    1. 结构伪类

    根据 W3C 规范,结构伪类用来做下面的事:

    …允许选择位于文档树的额外信息,但不能用其他简单的选择器或组合选择器代替。

    这意味着我们拥有了能根据选择器在文档中的所处位置,动态选择内容的选择器。那么让我们从文档本身开始,即 :root 伪类。

    W3C 上的 Level 3 选择器

    E:root

    :root 伪类选择页面的根元素。十有八九根节点是 元素,例如:

    :root { background-color: #fcfcfc; }

    除了给 元素设定样式,这个伪类基本没什么价值,可能也就描述性稍强些:

    html { background-color: #fcfcfc; }

    回到那张 iPhone 表单,为其添加基本的文本和背景样式:

    :root {
    color: #fff;
    text-shadow: 0 -1px 0 rgba(0,0,0,0.8);
    background: url(…/images/background.png) no-repeat #282826; }

    E:nth-child(n)

    :nth-child() 选择器可能需要一些实践才能完全理解。最简单的记忆方法是使用关键词“奇数或偶数”(odd 或 even),因为在显示由行列组成的数据表格时,这将非常有用。例如,我们可以使用下列内容:

    ul li:nth-child(odd) {
    background-color: #666;
    color: #fff; }

    这将使无序列表中的每个奇数行高亮显示。您可能会发现在表格中使用这种技术非常方便。例如:

    table tr:nth-child(even) { … }

    :nth-child 选择器更明确灵活,因此,你可以选择列表的第三个元素,像这样:

    li:nth-child(3) { … }

    请注意 n 并不是从零开始,第一个元素是 :nth-child(1),第二个是 :nth-child(2),以此类推。

    我们也可以利用一些简单的代数,使它变得更加精彩。考虑以下代码:

    li:nth-child(2n) { … }

    当我们以这种方式使用 n,它代表对所有正整数,直到文档耗尽可选择的元素。在这种情况下,它会选择下列列表项:

    • 未选择元素 (2 × 0)
    • 第 2 个元素 (2 × 1)
    • 第 4 个元素 (2 × 2)
    • 第 6 个元素 (2 × 3)
    • 第 8 个元素 (2 × 4)

    这实际上和使用 :nth-child(even) 完全一致。因此我们混入点东西:

    li:nth-child(5n) { … }

    对应选择的节点元素:

    • 未选择元素 (5 × 0)
    • 第 5 个元素 (5 × 1)
    • 第 10 个元素 (5 × 2)
    • 第 15 个元素 (5 × 3)
    • 第 20 个元素 (5 × 4)

    对于长列表或表格而言,也许这将很有用,也可能完全无用。我们还可以在这一公式中执行数字加减法:

    li:nth-child(4n + 1) { … }

    对应选择的节点元素:

    • 第 1 个元素 ((4 × 0) + 1)
    • 第 5 个元素 ((4 × 1) + 1)
    • 第 9 个元素 ((4 × 2) + 1)
    • 第 13 个元素 ((4 × 3) + 1)
    • 第 17 个元素 ((4 × 4) + 1)

    这里 SitePoint 指出了一个怪癖的功能,如果你将 n 设置为负值,则可以像这样选择前 x 项。

    li:nth-child(-n + x) { … }

    如果你期望选择前 5 项,可以这样写:

    li:nth-child(-n + 5) { … }

    对应选择的节点元素:

    • 第 5 个元素 (-0 + 5)
    • 第 4 个元素 (-1 + 5)
    • 第 3 个元素 (-2 + 5)
    • 第 2 个元素 (-3 + 5)
    • 第 1 个元素 (-4 + 5)
    • 未选择元素 (-5 + 5)
    • 未选择元素 (-6 + 5)

    如果你想要根据热门程度来列数据条目,并予以突出显示,也就是说,前十项可能是很有用的。

    WebDesign & Such 创建了 斑马样式示例,这应该是一个 :nth-child 的最佳实践。

    使用 CSS3 设置表格的斑马样式

    如果没有需要设置样式的表格,那么你可以 Webvisionary Awards 奖已经做的和使用:第n -孩子式交替其网站部分。这里的css:

    如果你的表格都不需要设置样式,那么你可以像 Webvisionary Awards 那样,使用 :nth-child 设置网站区块的交替样式。CSS 代码如下:

    section > section:nth-child(even) {
    background:rgba(255,255,255,.1)
    url("../images/hr-damaged2.png") 0 bottom no-repeat;
    }

    其效果很细微,但它增加了一个陈旧浏览器不支持的细节。

    Webvisionary Awards 上使用的 :nth-child 选择器

    iPhone 表单案例

    继续回到那张 iPhone 表单案例,这个案例中几乎很少地方可以使用 :nth-child 伪类,但值得注意的一点是,我们期望对前三个字段集的 label 标签隐藏,取而代之使用占位符(placeholder)文本替代。CSS 代码如下:

    form:nth-child(-n+3) label { display: none; }

    这里,我们寻找

    元素的前三个子节点,然后选取 label 元素,可以使用 display:none; 来隐藏。

    E:nth-last-child(n)

    我们并不仅仅满足于 :nth-child() 伪类,W3C 也给我们提供了 :nth-last-child(n) 伪类。它和 :nth-child() 的表现非常相似,除了反向操作,从最后一个向开始计算的功能。

    li:nth-last-child(1) { … }

    上述将选择列表中的最后一个元素,而下面将选择倒数第二个元素:

    li:nth-last-child(2) { … }

    当然,你也可以使用其他规则:

    li:nth-last-child(2n+1) { … }

    但你可能更倾向于使用以下方法选择最后五个列表元素(以上面讨论的逻辑为基础):

    li:nth-last-child(-n+5) { … }

    如果这仍然没有太大的意义,Lea Verou 创造了一个有用的 CSS3 结构伪类选择器测试工具,值得一试。

    CSS3 结构伪类选择器测试工具

    iPhone 表单案例

    在案例中,我们可以使用 :nth-last-child 来为“Card number”字段添加圆角。以下 CSS 代码可能过于具体,但至少提供了一个关联伪类的方法:

    fieldset:nth-last-child(2) input:nth-last-of-type(3) {
    border-radius: 10px; }

    我们首先抓住倒数第二个字段,选择其中倒数第三个字段(这个案例中,是“Card Number”字段)。然后,我们添加一个圆角效果(border-radius)。

    :nth-of-type(n)

    现在我们将做得更加具体,只为特定类型的元素设定样式。例如,假设你想使得文章第一段具有较大的字体。CSS 代码如下:

    article p:nth-of-type(1) { font-size: 1.5em; }

    也许你要文章中的部分图片右对齐,另一部分左对齐。则可以使用关键字来控制:

    article img:nth-of-type(odd) { float: right; }
    article img:nth-of-type(even) { float: left; }

    通过 :nth-child() 和 :nth-last-child(), 你可以使用代数表达式:

    article p:nth-of-type(2n+2) { … }
    article p:nth-of-type(-n+1) { … }

    值得记住的是如果需要获得这些指定的目标元素,使用描述性的 CSS 类名可能更合理。

    Simon Foster 创建了一个 关于 45 张 RPM 唱片集的漂亮图表,并且使用 :nth-of-type 来为某些数据设置样式。以下是他的代码片段,CSS 中各流派类型都做了区分。

    ul#genre li:nth-of-type(1) {
    width:32.9%;
    background:url(images/orangenoise.jpg);
    }
    ul#genre li:nth-of-type(2) {
    width:15.2%;
    background:url(images/bluenoise.jpg);
    }
    ul#genre li:nth-of-type(3) {
    width:13.1%;
    background:url(images/greennoise.jpg);
    }

    网站上是这样呈现的:

    For the Record 中的 :nth-of-type 选择器应用

    iPhone 表单案例

    比方说,我们希望偶数序号的输入框元素有底部圆角。可以用 CSS 实现这一点:

    input:nth-of-type(even) {
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px; }

    该案例中,我们只期望应用到 “payment” 字段,因为个人信息含有三个文本输入框。处理方法有些棘手,要确保不会选择任何单选框。最终 CSS 代码:

    payment input:nth-of-type(even):not([type=radio]) {

    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px;
    border-bottom: 1px solid #999;
    margin-bottom: 10px; }

    我们将稍后讲解 :not 伪类。

    :nth-last-of-type(n)

    现在来看看 :nth-last-of-type() 从选定元素的末尾开始,并且倒序工作。

    要选择文章的最后一段,可以这样使用:

    article p:nth-last-of-type(1) { … }

    当文章不确定是否以段楼你可能会选择这个选择器来代替 :last-child 伪类。

    :first-of-type 和 :last-of-type

    如果 :nth-of-type() 和 :nth-last-of-type() 对你而言不太灵活,你可以使用更简单的选择器取而代之,例如:

    article p:nth-of-type(1) {
    font-size: 1.5em; }

    也可以这么搞:

    article p:first-of-type {
    font-size: 1.5em; }

    正如你所期望的那样,使用 :last-of-type 效果完全一样,只不过从后续元素开始查找而已。

    iPhone 表单案例

    我们可以在这张表单中结合使用 :first-of-type 和 :last-of-type,特别是用于制作圆角。CSS 如下:

    fieldset input:first-of-type:not([type=radio]) {
    border-top-left-radius: 10px;
    border-top-right-radius: 10px; }

    fieldset input:last-of-type:not([type=radio]) {
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px; }

    第一行 CSS 对所有具有 :first-of-type 伪类的 input 元素增加了圆角上边框,并且所在字段不是单选按钮。第二行对字段内的最后一个 input 元素增加圆角下边框。

    :only-of-type

    还有另一个选择器 :only-of-type()。用于选择那些和它父元素中与自身同类型的元素。例如下面的代码:

    p {
    font-size: 18px; }

    p:only-of-type {
    font-size: 18px; }

    第一个选择器将影响到页面中的所有 p 元素,第二个选择器只会影响它父亲节点下的所有 p 元素。

    如果数据库查询只返回一个结果数据,为这个内容设置样式时,用 :only-of-type 可能会很方便。

    Devsnippet 创建了一个 Demo,说明如何在多个图片中为单个图片定义样式。

    Devsnippet’s 的 :only-of-type 案例

    iPhone 表单案例

    这张表单中,我们可以确保所有输入字段,无论在顶部还是底部,都有圆角效果,并且是该输入字段的唯一子节点。CSS 代码如下:

    fieldset input:only-of-type {
    border-radius: 10px; }

    :last-child

    这是一个奇怪的地方::first-child 是 CSS2 的规范,但 :last-child 却在 CSS3 中才出现。也不需要过多语言解释,:last-child 用于选择父元素下的最后一个子节点。例如:

    li {
    border-bottom: 1px solid #ccc; }

    li:last-child {
    border-bottom: none; }

    这是一个从列表底部消除边框的有用方法,在 WordPress 小工具中可以经常看到这种应用。

    Rachel Andrew 在他的 Cleaner Code With CSS3 Selectors 文章里谈论了 :last-child 和其他 CSS 伪类。他告诉我们如何使用这个伪类创建一份良好格式的图片画廊,而无需额外的 CSS 类。

    Rachel Andrew 的 :last-child 伪类使用案例

    :only-child

    如果某个元素是它的父节点的唯一子节点,那么你可以使用 :only-child 选择它。不像 :only-of-type 伪类,并且和元素类型无关。例如:

    li:only-child { … }

    我们可以使用它来选择

        中的单个列表项。

        :empty

        最后,结构伪类中,我们还有一个 :empty。毫不奇怪,这个选择器只会选择那些没有子节点和文本节点的元素。如果从数据库中动态输入内容进行处理,这可能会非常有用。

        results:empty {

        background-color: #fcc; }

        您可以使用该伪类来让用户注意搜索无结果的情况。

        1. 目标伪类

        :target

        这是我最喜欢的伪类之一,因为它使我们可以基于 URL 对页面元素定义样式。如果 URL 有一个标识符(即带有一个 # 符号),那么 :target 伪类将为以该标识符为 id 属性的元素设置样式。比如以下的链接:

        http://www.mangguo.org/how-to-use-css3-pseudo-classes#summary

        id 属性为 summary 的区块现在可以这样设置样式:

        :target {
        background-color: #fcc; }

        对于已经被元素外部链接指向的页面元素来说,这是一个伟大的举措。你也可以使用它来高亮加了锚点的内容。

        或许,最令人印象深刻的 :target 使用案例是 Corey Mwamba 的绿色滚动网站。他使用了一些富有创意的 CSS3 和 :target 伪类来创建动态的 Tab 导航效果。Demo 稿中包含了一些 CSS3 的巧妙用法,说明了伪类如何和其他 CSS 选择器结合使用。

        Corey Mwamba 的绿色滚动网站

        另外还有一个有趣的例子 Web Designer Notebook。利用了 :target 和 Webkit 动画来高亮目标 div 中的大块文本。Chris Coyier 还创建了一个基于 :target 伪类的 Tab 系统,发布在 CSS-Tricks 站点上。

        iPhone 表单案例

        这如我的 Demo 那样,我在顶部添加了一个导航栏,用于锚点定位到不同的表单区域。我们可以高亮任何区块:

        :target {
        background-color: rgba(255,255,255,0.3);

        -webkit-border-radius:
        10px;}

        1. UI 元素状态伪类

        :enabled 和 :disabled

        UI 元素伪类包括 :checked,:enabled,:disabled 三个。可以允许根据元素状态来设定样式(通常是表单元素)。状态可以由用户设置(:checked)或由开发者设置(:enabled 和:disabled)。例如,我们可以使用下列内容:

        input:enabled {
        background-color: #dfd; }

        input:disabled {
        background-color: #fdd; }

        这将更有利于给予用户反馈,让他们知道可以可以填写、什么不能填写,你会经常看到这样的依赖 JavaScript 的动态特征。

        iPhone 表单案例

        为了实践说明 :disabled,我已经禁用表单的“提交”按钮,并加入这行 CSS:

        :disabled {
        color: #600; }

        按钮文字变红了!

        :checked

        第三个伪类是 :checked,用于处理元素的状态,如复选框或单选按钮。这对用户来说能给予非常有益的反馈,告诉他们选中了哪些。例如:

        input[type=radio]:checked {
        font-weight: bold; }

        iPhone 表单案例

        当按钮按下时,我们可以用 CSS 来突出显示每个按钮旁边的文本:

        input:checked + label {
        text-shadow: 0 0 6px #fff; }

        我们首先选择任意已选中的 input 元素,然后查找包含目标文本的临近 元素,并使用简单的 text-shadow 属性来装饰。

        1. 否定伪类

        这是我最喜欢的另一种选择器,因为它会选中除了指定元素之外的全部元素。例如:

        :not(footer) { … }

        这将选中页面上除了 footer 标签之外的任何元素,在网页上是不是一个页脚元素的一切。用于表单输入框时,可以实现单个输入框的突出显示。

        input:not([type=submit]) { … }
        input:not(disabled) { … }

        第一行选择除了 type 类型为 submit 的所有 input 元素。第二个选择所有不是 disabled 状态的 input 元素。

        iPhone 表单案例

        你已经切切实实看了 :not 选择器的作用。当与其他 CSS3 伪类混用时,他将变得更加强大。让我们来仔细看个例子:

        fieldset input:not([type=radio]) {
        margin: 0;
        width: 290px;
        font-size: 18px;
        border-radius: 0;
        border-bottom: 0;
        border-color: #999;
        padding: 8px 10px;}

        在这里,我们选择字段元素内不是单选按钮的 input 输入框。这在表单中是很常见的,因为文本输入框、下拉选择框、单选按钮、提交按钮往往是风格不一的。点此查看最终的表单效果

        1. 旧瓶装新酒

        让我们回到文章开头的 a:link。 HTML5 为 元素带来了令人兴奋的变化,赋予 CSS3 伪类更多的功能。

        元素现在可以嵌套块级元素,使整块的页面区块成为链接(只要这些部分不包含其他交互元素)。之前需要通过 JavaScript 来实现的,现在可以使用 嵌套方案轻松实现了。例如:

        123

        CSS 伪类的含义是,你可以随意为一个

        设定样式,无论它是被悬停(a:hover)活着被激活(a:active),像这样:

        a:hover #advert {
        background-color: #f7f7f7; }

        减少对 JavaScript 代码的以来,并能适当增强代码语义总归是件好事。

        1. 跨浏览器兼容性

        你肯定会问,IE8(或更早)不支持任何形式的 CSS3 选择器,即使最新的 Chrome、Opera、Safari 和 Firefox 都支持良好。在你的血液沸腾前,请考虑以下解决方案。

        Internet Explorer 9

        你可能对微软这款最新的 IE9 浏览器并不非常知情。但事实上它相当不错。虽然我并不指望读者和我想法一致,值得记住的是,IE 是世界上最为广泛流行的浏览器,和 Windows Update 和微软全球性的营销活动下,希望在不久的将来可以看到 IE9 成为主流。这对于网页设计者是好事,对伪类选择器也是好事。但是 IE8 和他的祖先们怎么办?

        Internet Explorer 9 来了

        让我们的老朋友 JavaScript 来救援 CSS3 伪类吧。我特别喜欢 Keith Clark 的 Selectivizr。Keith 组建了一个适用于各种 JavaScript 类库的脚本,为早期版本的 IE 浏览器增加了 CSS3 伪类选择器功能。但是要注意,各种类库支持并不完全一致:如果你在 Mootools 上使用 Selectivizr,那么所有的伪类将可用,但如果你使用 jQuery,只有部分伪类可以正常工作。

        Selectivizr

        Keith recently 发布了一个 jQuery 插件来支持以下 CSS3 伪类:

        • :first-of-type
        • :last-of-type
        • :only-of-type
        • :nth-of-type
        • :nth-last-of-type

        另外,也值得关注下 Dean Edwards 写的 ie7.js 脚本。这份脚本解决了一些 IE 相关问题,包括 CSS3 伪类。

        因此,我们可以开始使用 CSS3 伪类了吗?

        我想就这个问题的答案取决于你如何看待 JavaScript 这玩意儿。现实是伪类完全可以被 class 和 id 替代。另一个现实是,在设置复杂布局样式时,伪类非常有用并且理所而然、自然而然。如果你发现伪类提高了你的 CSS 可读性,并减少了 HTML 中的非语义 CSS 类,这也正式我建议拥抱 CSS3 伪类的原因。

        你可以使用两个选择器和一个 class 名,但只是重复工作。这也意味着使用伪类并不是必须。如果你没有坚持原则,代码可能看起来像这样:

        li:nth-of-type(3),
        li.third { … }

        这种方法并不像使用伪类灵活,因为在内容变化时你需要同事改变 HTML 结构和 CSS 内容。

        如果用户没有启用 JavaScript 会导致你陷入困境。许多网页设计师认为,功能(即 JavaScript)是和布局(即 CSS)不同的,所以你不应该依赖于 JavaScript 使 IE8 和早期浏览器支持伪类。

        虽然我原则上统一,实际上我认为,相对于 99% 的用户提供最佳的经验和为剩余的 1% 用户做出让步,显然前者更好(假如你有大量无脚本的用户,那就另当别论)。

        按照你的网站分析,并准备成为一个网页设计师不断提高自己的技能。更重要的是,尽力为广大用户提供最好的体验。

        1. 最后的思考

        IE8 对伪类支持的缺乏,很难不让人感到沮丧。可以说,浏览器以 JavaScript 方式计算和重新计算页面样式将对渲染速度造成影响,但因为所有其他主要浏览器现在支持这些选择器。令人沮丧的是,如果没有 JavaScript Hack 方案,我们的大多数用户无法从中受益。

        但就像 Farnsworth 说的,Internet Explorer 9 的曙光将是一道分水岭,微软已确保其新的浏览器支持每个本文所讨论的选择器。

        CSS3 伪类选择器不会大块占用你的样式表。他们是特有而充满活力的。而且更可能的是,至少在最初阶段,要补充性地优化,而不是实现一个整体的网页。也许你想丢弃列表最后一项的下边框,或向用户提供视觉反馈,因为他们在填写表格。CSS3 让这些都成为可能,并且会逐渐成为主流,我希望这将成为 Web 设计工具箱的一部分。

        1. 相关参考

        英文原稿:How To Use CSS3 Pseudo-Classes | Smashing Magazine

        翻译整理:如何使用 CSS3 伪类 | 芒果小站

        CSS3 :nth-child()伪类选择器:http://www.cnblogs.com/kiracn/archive/2009/12/17/1626742.html

    javascript call()与apply()

    1、方法定义

    call方法:
    语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
    定义:调用一个对象的一个方法,以另一个对象替换当前对象。
    说明:
    call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
    如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

    apply方法:
    语法:apply([thisObj[,argArray]])
    定义:应用某一对象的一个方法,用另一个对象替换当前对象。
    说明:
    如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
    如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

    2、常用实例

    a、

    function add(a,b)
    {
    alert(a+b);
    }
    function sub(a,b)
    {
    alert(a-b);
    }

    add.call(sub,3,1);
    这个例子中的意思就是用 add 来替换 sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4); // 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。

    b、

    function Animal(){
    this.name = "Animal";
    this.showName = function(){
    alert(this.name);
    }
    }

    function Cat(){
    this.name = "Cat";
    }

    var animal = new Animal();
    var cat = new Cat();

    //通过call或apply方法,将原本属于Animal对象的showName()方法交给对象cat来使用了。
    //输入结果为"Cat"
    animal.showName.call(cat,",");
    //animal.showName.apply(cat,[]);
    call 的意思是把 animal 的方法放到cat上执行,原来cat是没有showName() 方法,现在是把animal 的showName()方法放到 cat上来执行,所以this.name 应该是 Cat

    c、实现继承

    function Animal(name){
    this.name = name;
    this.showName = function(){
    alert(this.name);
    }
    }

    function Cat(name){
    Animal.call(this, name);
    }

    var cat = new Cat("Black Cat");
    cat.showName();
    Animal.call(this) 的意思就是使用 Animal对象代替this对象,那么 Cat中不就有Animal的所有属性和方法了吗,Cat对象就能够直接调用Animal的方法以及属性了.

    d、多重继承

    function Class10()
    {
    this.showSub = function(a,b)
    {
    alert(a-b);
    }
    }

    function Class11()
    {
    this.showAdd = function(a,b)
    {
    alert(a+b);
    }
    }

    function Class2()
    {
    Class10.call(this);
    Class11.call(this);
    }
    很简单,使用两个 call 就实现多重继承了
    当然,js的继承还有其他方法,例如使用原型链,这个不属于本文的范畴,只是在此说明call 的用法。说了call ,当然还有 apply,这两个方法基本上是一个意思,区别在于 call 的第二个参数可以是任意类型,而apply的第二个参数必须是数组,也可以是arguments
    还有 callee,caller..

    盒子模型

    css盒子模型中包括几种重要的属性,包括margin、border、padding以及content。但浏览器对其盒子模型的解释则有所不痛,启用标准模式还是IE(怪)模式是与当前页面的文档声明相关的。

    借用网上一幅图:image

    这是标准盒子模型,可以看出,其宽和高均为其中content的宽高。

    对于IE来说,image,其css盒子的宽高则包括了border,padding以及content。

    如何判断当前的页面使用了哪种解释模型呢,这就与文档声明有关。在文档顶部增加了doctype声明则会被解释为标准模型,若不加则与具体的浏览器相关了,ie以ie盒子的方式解释,ff仍然以标准盒子方式解释。

    css2.1规范即为标准模型,只是IE“自以为是”。为了解决这种“自以为是”的行为,css3规定了这个属性,box-sizing,其值为“content-box”和“border-box”。

    当box-sizing为content-box时,解释方法即IE盒子模型;当为border-box时,解释方法为标准模型。

    Firefox使用-moz-box-sizing,safari/webkit使用-webkit-box-sizing,而opera使用box-sizing。

    但为什么IE会把盒子模型解释成border-size,而这两种模式又有什么样的用法呢?等我熟悉熟悉再说~

    既然说到盒子模型,再介绍刚学到的几个新的css3属性,background-origin,background-clip.

    background-origin:即用来决定图片的原始起始位置,可选值为:content-box,padding-box,border-box。默认值为padding。

    目前在FF中要加-moz-,safari/chrome中要加-webkit-,值为content,padding,border。

    background-clip:即用来对背景图片进行适当的裁剪,可选值同background-origin。

    含义是指,背景图片无论初始值设置在哪里,但只有在background-clip设置的范围内的部分才会显示出来。

    这个具体的用法需要再熟悉一下。

    jquery $(document).ready() 与window.onload的区别

    Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的。

    1.执行时间
    window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行。
    $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。
    2.编写个数不同
    window.onload不能同时编写多个,如果有多个window.onload方法,只会执行一个
    $(document).ready()可以同时编写多个,并且都可以得到执行
    3.简化写法
    window.onload没有简化写法
    $(document).ready(function(){})可以简写成$(function(){});

    以 浏览器装载文档为例,在页面加载完毕后,浏览器会通过 Javascript 为 DOM 元素添加事件。在常规的 Javascript 代码中,通常使用 window.onload 方法,而在 Jquery 中,使用的是 $(document).ready() 方法。 $(document).ready() 方法是事件模块中最重要一个函数,可以极大的提高 Web 应用程序的速度。

    window.load $(document).ready()
    执行时机 必须等待网页中所有的内容加载完毕后 ( 包括图片 ) 才能执行 网页中所有 DOM 结构绘制完毕后就执行,可以能 DOM 元素关联的内容并没有加载完
    编写个数 不能同时编写多个
    以下代码无法正确执行:
    window.onload = function(){
    alert(“text1”);
    };
    window.onload = function(){
    alert(“text2”);
    };
    结果只输出第二个 能同时编写多个
    以下代码正确执行:
    $(document).ready(function(){
    alert(“Hello World”);
    });
    $(document).ready(function(){
    alert(“Hello again”);
    });
    结果两次都输出
    简化写法 无 $(function(){
    // do something
    });

    另外,需要注意一点,由于在 $(document).ready() 方法内注册的事件,只要 DOM 就绪就会被执行,因此可能此时元素的关联文件未下载完。例如与图片有关的 html 下载完毕,并且已经解析为 DOM 树了,但很有可能图片还没有加载完毕,所以例如图片的高度和宽度这样的属性此时不一定有效。要解决这个问题,可以使用 Jquery 中另一个关于页面加载的方法 ---load() 方法。 Load() 方法会在元素的 onload 事件中绑定一个处理函数。如果处理函数绑定给 window 对象,则会在所有内容 ( 包括窗口、框架、对象和图像等 ) 加载完毕后触发,如果处理函数绑定在元素上,则会在元素的内容加载完毕后触发。
    Jquery 代码如下:
    $(window).load(function (){
    // 编写代码
    });等价于 JavaScript 中的以下代码
    Window.onload = function (){
    // 编写代码
    }

    ——————————————————————————————

    最近在改一个嵌入在frame中的页面的时候,使用了jquery做效果,而页面本身也绑定了onload事件。改完后,Firefox下测试正常流畅,IE下就要等个十几秒jquery的效果才出现,黄花菜都凉了。

    起初以为是和本身onload加载的方法冲突。网上普遍的说法是$(document).ready()是在页面DOM解析完成后执行,而onload事件是在所有资源都准备完成之后才执行,也就是说$(document).ready()是要在onload之前执行的,尤其当页面图片较大较多的时候,这个时间差可能更大。可是我这页面分明是图片都显示出来十几秒了,还不见jquery的效果出来。

    删了onload加载的方法试试,结果还是一样,看来没有必要把原本的onload事件绑定也改用$(document).ready()来写。那是什么原因使得Firefox正常而IE就能呢?接着调试,发现IE下原来绑定的onload方法竟然先于$(document).ready()的内容执行,而Firefox则是先执行$(document).ready()的内容,再执行原来的onload方法。这个和网上的说法似乎不完全一致啊,呵呵,有点意思,好像越来越接近真相了。

    翻翻jquery的源码看看$(document).ready()是如何实现的吧:

    复制代码 代码如下:
    if ( jQuery.browser.msie && window == top ) (function(){
    if (jQuery.isReady) return;
    try {
    document.documentElement.doScroll("left");
    } catch( error ) {
    setTimeout( arguments.callee, 0 );
    return;
    }
    // and execute any waiting functions
    jQuery.ready();
    })();
    jQuery.event.add( window, "load", jQuery.ready );

    结果很明了了,IE只有在页面不是嵌入frame中的情况下才和Firefox等一样,先执行$(document).ready()的内容,再执行原来的onload方法。对于嵌入frame中的页面,也只是绑定在load事件上执行,所以自然是在原来的onload绑定的方法执行之后才轮到。而这个页面中正好在测试环境下有一个访问不到的资源,那十几秒的延迟正是它放大出的时间差。

    文本多行省略号

    word-wrap:break-word; -webkit-line-clamp:2; display:-webkit-box; -webkit-box-orient:vertical; text-overflow:ellipsis;

    css3选择器-www.w3.org

    翻译自http://www.w3.org/TR/css3-selectors

    以上是废话

    1.3 此处未完全确认,相较于css3和css3的选择器,区别包括:

    • 基础定义改变(选择器、选择器组,简单选择器等),特别的,作为css2中简单选择器,如今被成为简单选择器序列,“简单选择器”作为这个序列的组成部分。
    • 允许在元素类型选择器上、通用选择器和类型选择器上增加可选的命名空间。
    • 一个新的组合器
    • 一个新的简单选择器,包括了匹配属性选择器的子字符串,以及新的伪类
    • 新的伪类,以及针对伪类的::书写习惯
    • 语法重写
    • 整合选择器、定义选择器集合
    • 选择器是一个css3 module,并且单独声明。其他声明可以关联到这个文档?
    • 声明拥有自己特有的测试组件

    1.4 选择器

    格式

    含义

    css级别

    所有元素

    2

    E

    E-类型选择器

    1

    E[foo]

    E,具有foo属性

    2

    E[foo="bar"]

    E,具有Foo属性,且值精确等于bar

    2

    E[foo~="bar"]

    E,具有Foo属性,值为一系列被空格分割,其中之一精确等于bar

    2

    E[foo^="bar"]

    E,具有foo属性,其值以bar开头

    3

    E[foo$="bar"]

    E,具有foo属性,其值以bar结尾

    3

    E[foo*="bar"]

    E,具有foo属性,其值包含bar

    3

    E[foo|="en"]

    E,具有foo属性,其值包含一系列以-分隔的词(从左开始),并以en开头(例如:lang伪类:html:lang(fr-be) 、 html:lang(de))

    2

    E:root

    E,文档根节点

    3

    E:nth-child(n)

    E的第n个孩子节点

    3

    E:nth-last-child(n)

    E的从最后一个孩子往前倒数第n个孩子节点

    3

    E:nth-of-type(n)

    E的type类型的第n个兄弟

    3

    E:nth-last-of-type(n)

    E的从最后一个孩子往前倒数第n个type类型的兄弟节点

    3

    E:first-child

    E的第一个孩子节点

    2

    E:last-child

    E的最后一个孩子节点

    3

    E:first-of-type

    E的类型的第一个兄弟

    3

    E:last-of-type

    E的类型的最后一个兄弟节点

    3

    E:only-child

    E的唯一一个孩子节点

    3

    E:only-of-type

    E的类型的唯一一个兄弟节点

    3

    E:empty

    没有子节点(也包括文本节点)的E

    3

    E:link

    E,作为超链接的锚点,其目标尚未被访问

    1

    E:visited

    或被访问过

    1

    E:active

    E在某个用户操作激活状态下

    1,2

    E:hover

    E:focus

    E:target

    E,作为某个提到的URI的目标

    3

    E:lang(fr)

    E在fr语言下(文档语言决定当前页面为何种语言)

    2

    E:enabled

    用户界面上的元素E,可用或禁用

    3

    E:disabled

    E:checked

    用户界面上的元素E,被选中状态(例如单选框,多选框)

    3

    E::first-line

    E的格式化的第一行

    1

    E::first-letter

    E的格式化的第一个字母

    1

    E::before

    在E元素之前创建内容

    2

    E::after

    在E元素之后创建内容

    2

    E.warning

    带有class为warning的元素E

    1

    E#myid

    带有id为myid的元素E

    1

    E:not(s)

    E,不符合简单选择器S

    3

    E F

    E的子孙F

    1

    E > F

    E的孩子F

    2

    E + F

    F元素,被E紧跟

    2

    E ~ F

    F元素,之前有个E

    3

    3。大小写不敏感?

    4、一个简单选择器,可能是类型选择器,通用选择器,属性选择器,类选择器,ID选择器或伪类

    6、带有namespace的CSS写法:

    • ns|E 在ns命名空间中的E
    • *|E 任意(或无)命名空间中的E
    • |E 没有命名空间的E
    • E 若没有默认命名空间声明,等同于*|E;否则等同于ns|E,ns为默认命名空间

    9、CSS计算规则
    * 0
    tag 1
    .class 10
    id 100

    匿名函数

    一、什么是匿名函数?

    在Javascript定义一个函数一般有如下三种方式:

    函数关键字(function)语句:
    function fnMethodName(x){alert(x);}
    函数字面量(Function Literals):
    var fnMethodName = function(x){alert(x);}
    Function()构造函数:
    var fnMethodName = new Function('x','alert(x);')
    上面三种方法定义了同一个方法函数fnMethodName,第1种就是最常用的方法,后两种都是把一个函数复制给变量fnMethodName,而这个函数是没有名字的,即匿名函数。实际上,相当多的语言都有匿名函数。

    二、函数字面量和Function()构造函数的区别

    虽然函数字面量是一个匿名函数,但语法允许为其指定任意一个函数名,当写递归函数时可以调用它自己,使用Function()构造函数则不行。
    var f = function fact(x) {
    if (x < = 1) return 1;
    else return x*fact(x-1);
    };
    Function()构造函数允许运行时Javascript代码动态的创建和编译。在这个方式上它类似全局函数eval()。
    Function()构造函数每次执行时都解析函数主体,并创建一个新的函数对象。所以当在一个循环或者频繁执行的函数中调用Function()构造函数的效率是非常低的。相反,函数字面量却不是每次遇到都重新编译的。
    用Function()构造函数创建一个函数时并不遵循典型的作用域,它一直把它当作是顶级函数来执行。
    var y = "global";
    function constructFunction() {
    var y = "local";
    return new Function("return y"); // 无法获取局部变量
    }
    alert(constructFunction()()); // 输出 "global"
    和函数关键字定义相比Function()构造器有自己的特点且要难以使用的多,所以这项技术通常很少使用。而函数字面量表达式和函数关键字定义非常接近。考虑前面的区别,虽然有消息说字面量的匿名函数在OS X 10.4.3下的某些webkit的引擎下有bug,但我们平常所说的匿名函数均指采用函数字面量形式的匿名函数。更多详细内容可以阅读《JavaScript: The Definitive Guide, 5th Edition》的Functions那章。

    三、匿名函数的代码模式

    昨天hedger wang在他的blog介绍了几种匿名函数的代码模式:

    错误模式:其无法工作,浏览器会报语法错。

    function(){
    alert(1);
    }();
    函数字面量:首先声明一个函数对象,然后执行它。
    (function(){
    alert(1);
    } ) ( );
    优先表达式:由于Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数。
    ( function(){
    alert(2);
    } ( ) );
    Void操作符:用void操作符去执行一个没有用圆括号包围的一个单独操作数。
    void function(){
    alert(3);
    }()
    这三种方式是等同的,hedger wang因为个人原因比较喜欢第3种,而在实际应用中我看到的和使用的都是第1种。

    四、匿名函数的应用

    《Javascript的一种模块模式》中的第一句话就是“全局变量是魔鬼”。配合var关键字,匿名函数可以有效的保证在页面上写入Javascript,而不会造成全局变量的污染。这在给一个不是很熟悉的页面增加Javascript时非常有效,也很优美。实际上,YUI以及其相应的范例中大量使用匿名函数,其他的Javascript库中也不乏大量使用。
    Javascript的函数式编程(functional programming)的基石。具体请看《用函数式编程技术编写优美的 JavaScript》和《函数式JavaScript编程指南》。

    Google HTML/CSS/JS代码风格指南

    背景

    本文档定义了HTML/CSS的编写格式和风格规则。它旨在提高合作和代码质量,并使其支持基础架构。适用于HTML/CSS文件,包括GSS文件。 只要代码质量是可以被维护的,就能很好的被工具混淆、压缩和合并。

    样式规则

    协议

    嵌入式资源书写省略协议头
    省略图像、媒体文件、样式表和脚本等URL协议头部声明 ( http: , https: )。如果不是这两个声明的URL则不省略。

    省略协议声明,使URL成相对地址,防止内容混淆问题和导致小文件重复下载。

    <script src="http://www.google.com/js/gweb/analytics/autotrack.js"></script> <script src="//www.google.com/js/gweb/analytics/autotrack.js"></script>

    /* 不推荐 /
    .example {
    background: url(http://www.google.com/images/example);
    }
    /
    推荐 */
    .example {
    background: url(//www.google.com/images/example);
    }
    排版规则

    缩进

    每次缩进两个空格。
    不要用TAB键或多个空格来进行缩进。

    • Fantastic
    • Great

    .example {
    color: blue;
    }
    大小写

    只用小写字母。
    所有的代码都用小写字母:适用于元素名,属性,属性值(除了文本和 CDATA ), 选择器,特性,特性值(除了字符串)。

    Home

    Google

    行尾空格

    删除行尾白空格。
    行尾空格没必要存在。

    What?_

    Yes please. 元数据规则

    编码

    用不带BOM头的 UTF-8编码。
    让你的编辑器用没有字节顺序标记的UTF-8编码格式进行编写。

    在HTML模板和文件中指定编码 . 不需要制定样式表的编码,它默认为UTF-8.

    (更多有关于编码的信息和怎样指定它,请查看 Character Sets & Encodings in XHTML, HTML and CSS。)

    注释

    尽可能的去解释你写的代码。
    用注释来解释代码:它包括什么,它的目的是什么,它能做什么,为什么使用这个解决方案,还是说只是因为偏爱如此呢?

    (本规则可选,没必要每份代码都描述的很充分,它会增重HTML和CSS的代码。这取决于该项目的复杂程度。)

    活动的条目

    用 TODO 标记代办事项和正活动的条目
    只用 TODO 来强调代办事项, 不要用其他的常见格式,例如 @@ 。

    附加联系人(用户名或电子邮件列表),用括号括起来,例如 TODO(contact) 。

    可在冒号之后附加活动条目说明等,例如 TODO: 活动条目说明 。

    {# TODO(cha.jn): 重新置中 #}

    Test
    • Apples
    • Oranges
    HTML代码风格规则

    文档类型

    请使用HTML5标准。
    HTML5是目前所有HTML文档类型中的首选: .

    (推荐用HTML文本文档格式,即 text/html . 不要用 XHTML。 XHTML格式,即 application/xhtml+xml , 有俩浏览器完全不支持,还比HTML用更多的存储空间。)

    HTML代码有效性

    尽量使用有效的HTML代码。
    编写有效的HTML代码,否则很难达到性能上的提升。

    用类似这样的工具 W3C HTML validator 来进行测试。

    HTML代码有效性是重要的质量衡量标准,并可确保HTML代码可以正确使用。

    <title>Test</title> This is only a test. <title>Test</title> This is only a test. 语义

    根据HTML各个元素的用途而去使用它们。
    使用元素 (有时候错称其为“标签”) 要知道为什么去使用它们和是否正确。 例如,用heading元素构造标题, p 元素构造段落, a 元素构造锚点等。

    根据HTML各个元素的用途而去使用是很重要的,它涉及到文档的可访问性、重用和代码效率等问题。

    All recommendations
    All recommendations 多媒体后备方案

    为多媒体提供备选内容。
    对于多媒体,如图像,视频,通过 canvas 读取的动画元素,确保提供备选方案。 对于图像使用有意义的备选文案( alt ) 对于视频和音频使用有效的副本和文案说明。

    提供备选内容是很重要的,原因:给盲人用户以一些提示性的文字,用 @alt 告诉他这图像是关于什么的,给可能没理解视频或音频的内容的用户以提示。

    (图像的 alt 属性会产生冗余,如果使用图像只是为了不能立即用CSS而装饰的 ,就不需要用备选文案了,可以写 alt="" 。)

    电子表格截图

    关注点分离

    将表现和行为分开。
    严格保持结构 (标记),表现 (样式),和行为 (脚本)分离, 并尽量让这三者之间的交互保持最低限度。

    确保文档和模板只包含HTML结构, 把所有表现都放到样式表里,把所有行为都放到脚本里。

    此外,尽量使脚本和样式表在文档与模板中有最小接触面积,即减少外链。

    将表现和行为分开维护是很重要滴,因为更改HTML文档结构和模板会比更新样式表和脚本更花费成本。

    <title>HTML sucks</title>

    HTML sucks

    I’ve read about this on a few sites but now I’m sure: HTML is stupid!!1

    I can’t believe there’s no way to control the styling of my website without doing everything all over again! <title>My first CSS-only redesign</title>

    My first CSS-only redesign

    I’ve read about this on a few sites but today I’m actually doing it: separating concerns and avoiding anything in the HTML of my website that is presentational.

    It’s awesome! 实体引用

    不要用实体引用。
    不需要使用类似 — 、 ” 和 ☺ 等的实体引用, 假定团队之间所用的文件和编辑器是同一编码(UTF-8)。

    在HTML文档中具有特殊含义的字符(例如 < 和 & )为例外, 噢对了,还有 “不可见” 字符 (例如no-break空格)。

    欧元货币符号是 “&eur;”。

    欧元货币符号是 “€”。
    可选标签

    省略可选标签(可选)。
    出于优化文件大小和校验, 可以考虑省略可选标签,哪些是可选标签可以参考 HTML5 specification。

    (这种方法可能需要更精准的规范来制定,众多的开发者对此的观点也都不同。考虑到一致性和简洁的原因,省略所有可选标记是有必要的。)

    <title>Spending money, spending bytes</title>

    Sic.

    <title>Saving money, saving bytes</title>

    Qed. type属性

    在样式表和脚本的标签中忽略 type 属性
    在样式表(除非不用 CSS)和脚本(除非不用 JavaScript)的标签中 不写 type 属性。

    HTML5默认 type 为 text/css 和 text/javascript 类型,所以没必要指定。即便是老浏览器也是支持的。

    <script src="//www.google.com/js/gweb/analytics/autotrack.js" type="text/javascript"></script> <script src="//www.google.com/js/gweb/analytics/autotrack.js"></script> HTML代码格式规则

    格式

    每个块元素、列表元素或表格元素都独占一行,每个子元素都相对于父元素进行缩进。
    独立元素的样式(as CSS allows elements to assume a different role per display property), 将块元素、列表元素或表格元素都放在新行。

    另外,需要缩进块元素、列表元素或表格元素的子元素。

    (如果出现了列表项左右空文本节点问题,可以试着将所有的 li 元素都放在一行。 A linter is encouraged to throw a warning instead of an error.)

    Space, the final frontier.

    • Moe
    • Larry
    • Curly
    Income Taxes
    $ 5.00 $ 4.50

    CSS代码风格规则

    CSS代码有效性

    尽量使用有效的CSS代码。
    使用有效的CSS代码,除非是处理CSS校验器程序错误或者需要专有语法。

    用类似W3C CSS validator 这样的工具来进行有效性的测试。

    使用有效的CSS是重要的质量衡量标准,如果发现有的CSS代码没有任何效果的可以删除,确保CSS用法适当。

    ID和class的命名

    为ID和class取通用且有意义的名字。
    应该从ID和class的名字上就能看出这元素是干嘛用的,而不是表象或模糊不清的命名。

    应该优先虑以这元素具体目来进行命名,这样他就最容易理解,减少更新。

    通用名称可以加在兄弟元素都不特殊或没有个别意义的元素上,可以起名类似“helpers”这样的泛。

    使用功能性或通用的名字会减少不必要的文档或模板修改。

    /* 不推荐: 无意义 不易理解 */

    yee-1901 {}

    /* 不推荐: 表达不具体 /
    .button-green {}
    .clear {}
    /
    推荐: 明确详细 */

    gallery {}

    login {}

    .video {}

    /* 推荐: 通用 */
    .aux {}
    .alt {}
    ID和class命名风格

    非必要的情况下,ID和class的名称应尽量简短。
    简要传达ID或class是关于什么的。

    通过这种方式,似的代码易懂且高效。

    /* 不推荐 */

    navigation {}

    .atr {}
    /* 推荐 */

    nav {}

    .author {}
    类型选择器

    避免使用CSS类型选择器。
    非必要的情况下不要使用元素标签名和ID或class进行组合。

    出于性能上的考虑避免使用父辈节点做选择器 performance reasons.

    /* 不推荐 /
    ul#example {}
    div.error {}
    /
    推荐 */

    example {}

    .error {}
    属性缩写

    写属性值的时候尽量使用缩写。
    CSS很多属性都支持缩写shorthand (例如 font ) 尽量使用缩写,甚至只设置一个值。

    使用缩写可以提高代码的效率和方便理解。

    /* 不推荐 /
    border-top-style: none;
    font-family: palatino, georgia, serif;
    font-size: 100%;
    line-height: 1.6;
    padding-bottom: 2em;
    padding-left: 1em;
    padding-right: 1em;
    padding-top: 0;
    /
    推荐 */
    border-top: 0;
    font: 100%/1.6 palatino, georgia, serif;
    padding: 0 1em 2em;
    0和单位

    省略0后面的单位。
    非必要的情况下 0 后面不用加单位。

    margin: 0;
    padding: 0;
    0开头的小数

    省略0开头小数点前面的0。
    值或长度在-1与1之间的小数,小数前的 0 可以忽略不写。

    font-size: .8em;
    URI外的引号

    省略URI外的引号。
    不要在 url() 里用 ( "" , '' ) 。

    @import url(//www.google.com/css/go.css);
    十六进制

    十六进制尽可能使用3个字符。
    加颜色值时候会用到它,使用3个字符的十六进制更短与简洁。

    /* 不推荐 /
    color: #eebbcc;
    /
    推荐 */
    color: #ebc;
    前缀

    选择器前面加上特殊应用标识的前缀(可选)。
    大型项目中最好在ID或class名字前加上这种标识性前缀(命名空间),使用短破折号链接。

    使用命名空间可以防止命名冲突,方便维护,比如在搜索和替换操作上。

    .adw-help {} /* AdWords */

    maia-note {} /* Maia */

    ID和class命名的定界符

    ID和class名字有多单词组合的用短破折号“-”分开。
    别在选择器名字里用短破折号“-”以外的连接词(包括啥也没有), 以增进对名字的理解和查找。

    /* 不推荐:“demo”和“image”中间没加“-” */
    .demoimage {}

    /* 不推荐:用下划线“_”是屌丝的风格 /
    .error_status {}
    /
    推荐 */

    video-id {}

    .ads-sample {}
    Hacks

    最好避免使用该死的CSS “hacks” —— 请先尝试使用其他的解决方法。
    虽然它很有诱惑力,可以当作用户代理检测或特殊的CSS过滤器,但它的行为太过于频繁,会长期伤害项目的效率和代码管理,所以能用其他的解决方案就找其他的。

    CSS代码格式规则

    声明顺序

    依字母顺序进行声明。
    都按字母顺序声明,很容易记住和维护。

    忽略浏览器的特定前缀排序,但多浏览器特定的某个CSS属性前缀应相对保持排序(例如-moz前缀在-webkit前面)。

    background: fuchsia;
    border: 1px solid;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    border-radius: 4px;
    color: black;
    text-align: center;
    text-indent: 2em;
    代码块内容缩进

    缩进所有代码块(“{}”之间)内容。
    缩进所有代码块的内容,它能够提高层次结构的清晰度。

    @media screen, projection {

    html {
    background: #fff;
    color: #444;
    }

    }
    声明完结

    所有声明都要用“;”结尾。
    考虑到一致性和拓展性,请在每个声明尾部都加上分号。

    /* 不推荐 /
    .test {
    display: block;
    height: 100px
    }
    /
    推荐 */
    .test {
    display: block;
    height: 100px;
    }
    属性名完结

    在属性名冒号结束后加一个空字符。
    出于一致性的原因,在属性名和值之间加一个空格(可不是属性名和冒号之间噢)。

    /* 不推荐 /
    h3 {
    font-weight:bold;
    }
    /
    推荐 */
    h3 {
    font-weight: bold;
    }
    选择器和声明分行

    将选择器和声明隔行。
    每个选择器和声明都要独立新行。

    /* 不推荐 /
    a:focus, a:active {
    position: relative; top: 1px;
    }
    /
    推荐 */
    h1,
    h2,
    h3 {
    font-weight: normal;
    line-height: 1.2;
    }
    规则分行

    每个规则独立一行。
    两个规则之间隔行。

    html {
    background: #fff;
    }

    body {
    margin: auto;
    width: 50%;
    }
    CSS元数据规则

    注释部分

    按组写注释。(可选)
    如果可以,按照功能的类别来对一组样式表写统一注释。独立成行。

    /* Header */

    adw-header {}

    /* Footer */

    adw-footer {}

    /* Gallery */

    .adw-gallery {}
    吐槽部分

    坚持一致原则

    如果你要编辑代码,先花几分钟看看它的代码风格,如果它这么做,那你也应该这么做。

    风格统一了,就有了一个共同思维的环境,参与者就可以专注的看你要说什么,而不是先想你是在说哪星球的语言。 虽然我们在这里提出统一样式规则,但就只是想让大家都知晓并借鉴而对自己的风格进行修正。 当然,保持自己独有的风格也是很重要的。balabala……

    Linux 命令行快捷键

    涉及在linux命令行下进行快速移动光标、命令编辑、编辑后执行历史命令、Bang(!)命令、控制命令等。让basher更有效率。

    说明

    Ctrl – k: 先按住 Ctrl 键,然后再按 k 键;
    CAlt – k: 先按住 Alt 键,然后再按 k 键;
    M – k:先单击 Esc 键,然后再按 k 键。
    移动光标

    Ctrl – a :移到行首
    Ctrl – e :移到行尾
    Ctrl – b :往回(左)移动一个字符
    Ctrl – f :往后(右)移动一个字符
    Alt – b :往回(左)移动一个单词
    Alt – f :往后(右)移动一个单词
    Ctrl – xx :在命令行尾和光标之间移动
    M-b :往回(左)移动一个单词
    M-f :往后(右)移动一个单词
    编辑命令

    Ctrl – h :删除光标左方位置的字符
    Ctrl – d :删除光标右方位置的字符(注意:当前命令行没有任何字符时,会注销系统或结束终端)
    Ctrl – w :由光标位置开始,往左删除单词。往行首删
    Alt – d :由光标位置开始,往右删除单词。往行尾删
    M – d :由光标位置开始,删除单词,直到该单词结束。
    Ctrl – k :由光标所在位置开始,删除右方所有的字符,直到该行结束。
    Ctrl – u :由光标所在位置开始,删除左方所有的字符,直到该行开始。
    Ctrl – y :粘贴之前删除的内容到光标后。
    Alt + t :交换光标处和之前两个字符的位置。
    Alt + . :使用上一条命令的最后一个参数。
    Ctrl – _ :回复之前的状态。撤销操作。
    Ctrl -a + Ctrl -k 或 Ctrl -e + Ctrl -u 或 Ctrl -k + Ctrl -u 组合可删除整行。

    Bang(!)命令

    !! :执行上一条命令。
    ^foo^bar :把上一条命令里的foo替换为bar,并执行。
    !wget :执行最近的以wget开头的命令。
    !wget:p :仅打印最近的以wget开头的命令,不执行。
    !$ :上一条命令的最后一个参数, 与 Alt - . 和 $_ 相同。
    !* :上一条命令的所有参数
    !_:p :打印上一条命令是所有参数,也即 !_的内容。
    ^abc :删除上一条命令中的abc。
    ^foo^bar :将上一条命令中的 foo 替换为 bar
    ^foo^bar^ :将上一条命令中的 foo 替换为 bar
    !-n :执行前n条命令,执行上一条命令: !-1, 执行前5条命令的格式是: !-5
    查找历史命令

    Ctrl – p :显示当前命令的上一条历史命令
    Ctrl – n :显示当前命令的下一条历史命令
    Ctrl – r :搜索历史命令,随着输入会显示历史命令中的一条匹配命令,Enter键执行匹配命令;ESC键在命令行显示而不执行匹配命令。
    Ctrl – g :从历史搜索模式(Ctrl – r)退出。
    控制命令

    Ctrl – l :清除屏幕,然后,在最上面重新显示目前光标所在的这一行的内容。
    Ctrl – o :执行当前命令,并选择上一条命令。
    Ctrl – s :阻止屏幕输出
    Ctrl – q :允许屏幕输出
    Ctrl – c :终止命令
    Ctrl – z :挂起命令
    重复执行操作动作

    M – 操作次数 操作动作 : 指定操作次数,重复执行指定的操作。

    怎么成为技术大牛(转自玉伯)

    微博和知乎上不时有人问,通常我会忽略掉。这类问题很容易回答,也很难回答。

    很容易回答,是因为见过太多牛人,细思他们的成功,无外乎勤奋、坚持。某人比你优秀,往往是因为他比你勤奋。

    很难回答,是因为要做到勤奋很难,要坚持更难。这需要自律,需要习惯。知易行难。

    以上话题很大,市面上的书籍汗牛充栋,推荐 《高效能人士的七个习惯》 。这类书籍,不能读完了事,关键之处在于,要真正去做。

    如何做到?个人比较推崇佛学里的做法。可以先亲近善知识,然后找到合适的导师,在一定环境下去修为。佛学里讲究皈依三宝,法宝是善知识,佛宝是导师,僧宝说的是环境。这道理和我们上学是一样的。为什么不能在家自学?因为自学太难,对绝大部分人都不适合。好的学校三宝俱足,能相对容易培养出好的人才。

    有了互联网,对技术人员来说,三宝很容易俱足。带上甄别的眼睛,网络上充满着善知识。比如哈佛等大学的公开课,比如很多优秀的技术书籍,还有各种推荐书单,只要用心,你就能发现。

    通过互联网,也将各个公司的技术高手直接变成了我们的导师。比如有很多优秀的开源社区,只要你懂得合理提问,就会有技术大拿很热心地帮助你。

    我们都是码农,也可以戏称为码僧,这样僧宝也就俱足了。你遇到的问题、困惑等等,可以访问 GitHub 、 StackOverflow 等寺庙,拿出来跟码僧们一起交流,一起取经。码僧们联合起来,就可以改变世界。

    除了互联网,在现实工作中,也可以尽量创造条件去具备三宝。去一个你认可的团队,去接近你心中的大牛,只要迈出第一步,就不会太难。只要多那么一点点勇气和决断。

    就说这么多。我离心中的大牛也还差着好几个山头,得埋头赶路了。

    IE layout详解

    引言:

    Internet Explorer 中有很多奇怪的渲染问题可以给他一个”layout”得到解决,John Gallant 和 Holly Bergevin把他归类为“dimensional bugs”(尺寸bug或者尺寸臭虫),意思是可以给对应的元素赋予宽度和高度解决;这给我们带来了一个问题:为什么layout可以改变渲染模式和元素 之间的关系?

    hasLayout定义:

    layout是IE/WIN里面的私有概念,它决定了一个元素如何显示以及约束其包含的内容、如何和其他元素进行相互作用和联系、如何响应和传递应用程序事件、用户事件等;

    layout的特性可以被某些css样式属性不可扭转的触发,一些html元素本身拥有layout缺省(默认)属性;

    Microsoft的开发者们决定一些元素应该获得一个“属性”(在面向对象的编程里),他们用了“hasLayout”属性,当渲染特性生效时,他的值被设置成true;

    当 Microsoft的私有属性hasLayout被设置成true时,我们说这个元素获得了布局(layout)或者说这个元素拥有了布局 (layout),布局元素可以是他们中的任何之一,如果那些元素拥有默认的layout布局或者通过设置合适的css属性使其获得布局 (layout);

    在非布局元素(non-layout)中,hasLayout不会被触发,比如说一个没有设置宽度和高度(没有尺寸定义)的div,他是所有非布局元素的祖宗;

    给 一个默认没有 layout 的元素赋予 layout 的方法包括设置可触发 hasLayout = true 的 CSS 属性。参考默认 layout 元素以及这些属性列表。没有办法设置 hasLayout = false , 除非把一开始那些触发 hasLayout = true 的 CSS 属性删除或重置。

    我们遇到的问题:

    hasLayout问题,影响那些有经验的设计师和代码人员,layout有许多不同寻常且难以预料的作用在盒子模型的展示,甚至有时会牵连他们的后代元素;

    一个元素有或者没有“layout”会引发下列问题:

    许多平常的IE浮动(float)bug;
    元素本身对一些基本属性的异常处理问题;
    容器和他的后代之间的外边距重叠(被随坏)问题;
    各种各样的列表问题;
    背景图像的定位偏差问题。
    使用脚本时遇到的浏览器之间处理不一致的问题。
    以上所列只是一个摘要和不完整的;

    Layout 的由来:

    不同于标准属性,也不像某些浏览器的私有 CSS 属性,layout 无法通过某一个 CSS 声明直接设定 。也就是说没有”layout属性”这么一个东西,元素要么本身自动拥有 layout,要么借助一些 CSS 声明悄悄地获得 layout。

    下列元素应该是默认具有 layout 的:

    , , ,
    ,

    , , , <textarea>, , <iframe>, , , 下列 CSS 属性和取值将会让一个元素获得 layout: position: absolute 绝对定位元素的包含区块(containing block)就会经常在这一方面出问题。 float: left|right 由于 layout 元素的特性,浮动模型会有很多怪异的表现。 display: inline-block 当一个内联级别的元素需要 layout 的时候往往就要用到它,这也可能也是这个 CSS 属性的唯一效果–让某个元素拥有 layout。”inline-block行为”在IE中是可以实现的,但是非常与众不同: IE/Win: inline-block and hasLayout 。 width: 除 “auto” 外的任意值 当遇到layout错误的展现效果是,一般都会尝试设定高度来修复 height: 除 “auto” 外的任意值 height: 1% 就在 Holly Hack 中用到。 zoom: 除 “normal” 外的任意值 IE专有属性。不过 zoom: 1 可以临时用做调试。 writing-mode: tb-rl MS专有属性。 overflow: hidden|scroll|auto 在 IE7 中,overflow 也变成了一个 layout 触发器,这个属性在之前版本 IE 中没有触发 layout 的功能,除非这个元素被其他情况触发添加到了一个盒子中; overflow-x|-y: hidden|scroll|auto overflow-x 和 overflow-y 是 CSS3 盒模型中的属性,尚未得到浏览器的广泛支持。他们在之前版本IE中没有触发 layout 的功能。 另外 IE7 的荧幕上又新添了几个 haslayout 的演员,如果只从 hasLayout 这个方面考虑,min/max 和 width/height 的表现类似,position 的 fixed 和 absolute 也是一模一样。 position: fixed min-width: 任意值 就算设为0也可以让该元素获得 layout。 max-width: 除 “none” 之外的任意值 min-height: 任意值 即使设为0也可以让该元素的 haslayout=true max-height: 除 “none” 之外的任意值 有关内联元素: 对于内联元素(可以是默认即为内联的比如 span 元素,也可以是 display: inline 的元素) width 和 height 只在 IE5.x 下和 IE6 或更新版本的 quirks 模式下触发 hasLayout 。而对于 IE6,如果浏览器运行于标准兼容模式下,内联元素会忽略 width 或 height 属性,所以设置 width 或 height 不能在此种情况下令该元素具有 layout。 zoom 总是可以触发 hasLayout,但是在 IE5.0 中不支持。 具 有”layout” 的元素如果同时也 display: inline ,那么它的行为就和标准中所说的 inline-block 很类似了:在段落中和普通文字一样在水平方向和连续排列,受 vertical-align 影响,并且大小可以根据内容自适应调整。这也可以解释为什么单单在 IE/Win 中内联元素可以包含块级元素而少出问题,因为在别的浏览器中 display: inline 就是内联,不像 IE/Win 一旦内联元素拥有 layout 还会变成 inline-block。 重置HasLayout: 如果没有其他属性再添加 hasLayout 的话,重置下列属性的默认值就会重新设置或破坏Haslayout: width, height (设为 “auto”) max-width, max-height (设为 “none”)(在 IE 7 中) position (设为 “static”) float (设为 “none”) overflow (设为 “visible”) (在 IE 7 中) zoom (设为 “normal”) writing-mode (从 “tb-rl” 设为 “lr-t) 使用者必须小心使用这些重置属性。 display 属性的不同:当用”inline-block”设置了 haslayout = true 时,就算在一条独立的规则中覆盖这个属性为”block”或”inline”,haslayout 这个标志也不会被重置为 false。 把 mid-width, mid-height 设为它们的默认值”0″仍然会赋予 hasLayout,但是 IE 7 却可以接受一个不合法的属性”auto”来重置 hasLayout。 hasLayout脚本属性: 我们已经选择参考把“hasLayout”属性作为一个脚本属性,以便把他与我们熟悉的CSS属性区分开来; 并没有方法可以直接设置或者重置hasLayout属性; hasLayout属性可以用来检查该元素是否有layout,例如它有一个ID=“eid”,然后可以直接在IE5.5地址栏里敲: javascript: alert(eid.currentStyle.hasLayout) 这样就可以检测出它的状态; IE 的Developer Toolbar允许你动态的检查当前元素的样式,当hasLayout的值为“true”时,它的值被呈现为“-1”,例如,如果你想编辑一个节点的属性 的时候,你可以CSS的“zoom”属性为“1”(zoom=1),这样可以触发那个hasLayout属性,以便dubug它; 另一件需 要考虑的是:layout怎么作用和影响脚本(script),例如:那些没有layout特性的元素的 clientWidth/clientHeight属性总是返回0,这对于新手来说是难以理解并且是莫名其妙的,并且它和 Mozilla(firefox)浏览器的作用有很大出入,我们能利用这个事实来为IE5.0做决定,就像这样,如果那个clientWidth是0,那 么我们说这个元素没有layout; CSS Hacks 在IE7和它以前的版本里,下面的这些hack已经得到了验证: John Gallant 和 Holly Bergevin在2003年发布了这个Holly hack: /* */ html .gainlayout { height: 1%; } /* */ 除了IE6下的标准模式里的行内元素,在IE5-6的所有版本里,这个hack都会触发所有元素的layout; 除了某些极稀少的height:0或者1px,它通常工作的很好; 除了在IE6的标准模式下(height:1%转化为height:auto,除非它的父元素有一个明确的高度),其他都与overflow:hidden是不相容的; 在IE7的标准模式下*html不会选择任何一个元素,它是没有任何效果的; 给IE6以及它以下的版本layout,也可以用这个underscore hack: .gainlayout { _height: 0; } 并且为了给IE7layout,我们可以用min-hight属性: .gainlayout { min-height: 0; } 二者选一的,这是比较有效的功能,就是conditional comments: <!–[if lte IE 6]> <style> .gainlayout { height: 1px; } </style> <![endif]–> 在外部样式表引入之时,插入一条受限制的注释,是比较简洁和可靠的解决办法: <!–[if lte IE 7]> 给IE6及他以下的版本设定高度总是被用到的,除非他和某些特性冲突(overflow:hidden);那些1%,1px或者0基本上都是相等的,但是那个1%有时候会出现一些问题(即使极少碰到); 在标准模式下给元素设定高度是不可用的,在IE7里应该尽可能避免(或者小心的使用:两个条件:<1>只能是百分值<2>其父元素必须没有确定的高度),鉴于这些原因,我们喜欢用:dispaly:inline-block或者zoom:1; 我们已经对那些浮动(float)元素试验了“holy”hacks,或者那些已经拥有宽度(width)的元素,记住这个目标就是:不能运用这些hacks在拥有height的元素上,因为这样会触发hasLayout=ture; 不要对所有的元素这样: {_height: 1px;} 这样是不合适的,因为它不仅仅让拥有layout的没有变好,反而改变了那些基本元素的渲染和展示; hack管理(management): 尽管IE7已经发布了,但是我们仍然不能预见将来的IE版本是否继续需要hasLayout来修复bug和他们是怎么相互作用的,所以用MS的私有属性zoom或者有田间的条件注释是明智的: <!–[if lt IE 7]><style> /* style for IE6 + IE5.5 + IE5.0 */ .gainlayout { height: 0; } </style><![endif]–> <!–[if IE 7]><style> .gainlayout { zoom: 1; } </style><![endif]–> zoom:1,它给IE5.5以上的所有版本里的任何元素layout(包括行内元素),但是这个规则在IE5.0里没有效果; 未知的副作用(尽管行内元素表现的像行内块元素); 如果一定要确定,zoom一定要被有条件的注释隐藏; 如果想得到一个更详尽的hasLayout触发和hasLayout在不同的IE版本里的比较的话,请参考这里:Thoughts on IE hack management. IE Mac简短介绍: IE Mac和IE for Windows是十分不同的,每一种都有自己的渲染引擎,IE Mac用任何方式都不知道hasLayout的行为,IE Mac渲染引擎是在向标准遵循模式靠近。

    关于Apple设备私有的apple-touch-icon属性详解

    以前我们用过favicon在浏览器给网站进行身份标识,用法如下:

    [html]view plaincopy

    现今移动设备越来越多,苹果为iOS设备配备了apple-touch-icon私有属性,添加该属性,在iPhone,iPad,iTouch的safari浏览器上可以使用添加到主屏按钮将网站添加到主屏幕上,方便用户以后访问。实现方法是在HTML文档的标签加入下面代码即可。

    [html]view plaincopy

    apple-touch-icon 标签支持sizes属性,可以用来放置对应不同的设备。

    57×57(默认值)的图标对应320×640的iphone老设备,72×72对应ipad,114×114对应retina屏的iPhone及iTouch。ipad3对应144×144的高分辨率。

    这是官方开发社区的详细介绍:

    Create different sizes of your app icon for different devices.If you’re creating a universal app, you need to supply app icons in all four sizes.

    For iPhone and iPod touch both of these sizes are required:

    57 x 57 pixels

    114 x 114 pixels (high resolution)

    For iPad, both of these sizes are required:

    72 x 72 pixels

    144 x 144 (high resolution)

    When iOS displays your app icon on the Home screen of a device, it automatically adds some visual effects to your icon so that it coordinates with the built-in icons on the Home screen. Specifically, iOS adds:

    Rounded corners

    Drop shadow

    Reflective shine (unless you prevent the shine effect)

    Note: You can prevent the addition of all effects by naming your icon apple-touch-icon-precomposed.png (this is available in iOS 2 and later).

    Ensure your icon is eligible for the visual enhancements iOS adds (if you want them). You should produce an image in PNG format that:

    Has 90° corners

    Does not have any shine or gloss

    所以最完善的写法应该是:

    [html]view plaincopy

    虽然官方都用的png图片做说明,但实际测试jpg格式也可用(不推荐),图片无需做圆角和高光效果,同Native App一样,系统会自动为图标添加圆角及高光。如果不想系统对图标添加效果,可以用apple-touch-icon-precomposed代替apple-touch-icon,这时我们提供的图标就要自己做圆角和高亮效果了。

    图标搜索的优先级如下:

    如果没有跟相应设备推荐尺寸一致的图标,那个会优先使用比推荐尺寸大,但最接近推荐尺寸的图标。

    如果没有比推荐尺寸大的图标,会优先选择最接近推荐尺寸的图标。

    如些有多个图标符合推荐尺寸,会优先选择包含关键字precomposed的图标。

    如果未在区域指定用link标签指定图标,会自动搜索网站根目录下有apple-touch-icon...或者 apple-touch-icon-precomposed…前缀的图标。 如设备推荐尺寸为57x57,优先级如下:

    apple-touch-icon-57×57-precomposed.png

    apple-touch-icon-57×57.png

    apple-touch-icon-precomposed.png

    apple-touch-icon.png

    在第三代 iPad 上有四种图标规格: 57x57, 72x72, 114x114, 144x144.

    由于 retina 图标的尺寸是标准图标大小的2倍,因此实际上我们只需要只做2款图标即可:114 x 114 和 144 x 144 。 将retina 图标的大小设置成标准图标的尺寸,那么IOS就会根据情况自动进行缩放了。

    [html]view plaincopy

    官方开发社区《iOS Human Interface Guidelines》地址http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/IconsImages/IconsImages.

    IE11下插入iframe内容

    if(navigator.userAgent.indexOf("MSIE")>0 || (navigator.userAgent.indexOf("Trident") > -1 && navigator.userAgent.indexOf("rv:11") > -1)){
      if(window.getSelection){
        var img = document.createElement("img");
        img.src = 'http://static.qyer.com/images/ask/temp/ask_append_img.png';
        img.className = 'js_load_pic';
        var m = editor.getSelection().getRangeAt(0);
        if(m){
          editor.document.body.appendChild(img);
        }
      }else{
      editor.document.selection.createRange().pasteHTML('') ;  }
    }else{
      editor.document.execCommand("insertHTML", null, '');
      //插入HTML
    }

    深入理解CSS中的行高

    行高计算方法:

    http://www.ddcat.net/blog/?p=227

    http://www.zhangxinxu.com/wordpress/?p=384

    深入理解CSS中的行高

    1. 基线、底线、顶线
    • 行高指的是文本行的基线间的距离。
    • 基线并不是汉字的下端沿,而是英文字母"x"的下端沿
    1. 行距、行高
    2. 内容区
    • 底线和顶线包裹的区域,实际中不一定看得到,但却是存在。
    1. 行内框
    • 行内框只是一个概念,它无法显示出来,但是它又确实存在
    • 它的高度就是行高
    • 在没有其他因素(padding)影响的时候,行内框等于内容区域
    • 行框(line box)。同行内框类似,行框是指本行的一个虚拟的矩形框
    • 行框高度等于本行内所有元素中行高最大的值

    元素对行高的影响

    • 对于行内元素如em、strong、span和等,其padding、margin、border-top、border-bottom 不会增加行高。
      padding会覆盖;margin将重置为0;border-top和border-bottom同样会覆盖。
      padding-left、padding-right、border-left和border-right可用。
    • img元素会影响行高

    css内容分享

    问题讨论:

    要求:

    ...
    ...
    - 上面.coupon-container背景色的部分最小高度是当前窗口高度 # 实现方案? 1. 常用CSS计量单位 2. CSS方法 3. 我对CSS的感受 # 常用CSS计量单位

    px,pt,em,rem,%

    计量单位

    名称

    备注

    px

    相对,像素

    相对类型,px是一个点,它不是自然界的长度单位,是屏幕上显示数据的最基本的点。如果点很小,那画面就清晰,我们称它为“分辨率高”,反之,就是“分辨率低”。所以,“点”的大小是会“变”的,也称为“相对长度”。

    pt

    相对,点

    绝对类型,确切的说法是一个专用的印刷单位“磅”,大小为1/72英寸。所以它是一个自然界标准的长度单位,也称为“绝对长度”。
    (每英寸的范围内,所能印刷的网点数。
    windows默认设置,文字为96DPI,1px=1/96英寸。
    pixel(dot)per inch,每英寸的像素(点)数,是一个率,表示了“清晰度”,“精度”)

    em

    相对值

    相对类型,相对父元素的大小,最终父元素为 font-size

    rem

    相对值

    相对类型,相对root element的font-size,也就是
    支持IE9及以上

    percent

    相对值

    相对类型,相对于父元素宽的大小。最外层的元素父元素是body

    除此之外,还有

    ‘vw’
    ‘vh’
    ‘vmin’
    ‘vmax’
    ‘ex’
    ‘mm’
    ‘cm’
    ‘in’
    ‘pc’
    ‘deg’
    ‘grad’
    ‘rad’
    ‘ms’
    ‘s’
    ‘Hz’
    ‘kHz’

    vw

    viewport width

    1vw = 1% of viewport width

    vh

    viewport height

    1vh = 1% of viewport height

    vmin/vmax

    min/max of viewport width and height

    vw和vh中较小/大的值

    ch

    字符0的宽度

    ex

    小写字符x的高度

    绝对长度说明

    in

    英寸Inches (1 英寸 = 2.54 厘米)

    cm

    厘米Centimeters

    mm

    毫米Millimeters

    pt

    点Points (1点 = 1/72英寸)

    pc

    皮卡Picas (1 皮卡 = 12 点)

    1ch/1ex

    几个CSS方法:

    calc()、toggle()、counter()、min()、 max()

    计算 calc() => CSS方法

    允许 + - * / 。其中+ - 必须有空格,* / 建议有。

    允许length、frequency、angle、time、number、integer

    但是注意,box-sizing与calc是互斥的。(尝试了一下貌似没问题)

    需要增加前缀

    • -moz-calc
    • -webkit-calc
    • calc

      兼容性

    题外话:PC版进行SEO的时候的考虑,前缀会在衡量之内。

    toggle() => css方法(cycle() => css方法)

    em { font-style: toggle(italic, normal); }
    ul { list-style-type: disc; }
         ul ul { list-style-type: toggle(disc, circle, square, box); }
    

    counter() => 计数器,

         counter(<identifier>, <style(同list-style-type)>)
    

    必须使用的属性:
    counter-reset:重置属性,并定义计数参数
    counter-reset: section 0 heading 0;
    counter-increment:值为计数参数,配合content
    counter-increment:[ ?]+ | none | inherit
    counter-increment:section 2;
    counter-increment:heading;
    content:配合使用
    content:counter(section);

    counters() => 重复插入计算器

    @counter-style(仅firefox支持,忽略)

    min() => 比较并取出最小的那个

    max() => 比较并取出最大的那个

    attr(attr-name) =>取出属性

    css2.1可返回一个字符串,css3中可返回多种不同类型(例如CSS colors, CSS integer, length, angle, time, frequency)

    兼容性:

    问题:

     css calc()方法是否会引起页面重排或重绘?
    

    我对css、手机端开发的一点建议

    • 推荐在移动端内使用最新的css方法
      移动端js运行效率较低,css动画流畅
      css可调用GPU进行处理,提高页面的流畅度,减少丢帧,尽量减少页面重绘重排次数。

      JS:requestAnimationFrame() -> setTimeout(polyfill)

    • 注意微信浏览器:www.html5test.com
      http://fe.2b6.me:3000/doc/info?id=9563ebcd-eae3-a09e-5d83-8cbdc9efb6e4

    • 尽量使用CSS来实现交互效果,减少JS的执行率
      CSS、HTML、JavaScript的相互关系。
      Html是内容,css是表现(皮肤,动画),JavaScript是交互
      什么样的行为属于交互,什么样的行为属于动画

    • 尽量减少移动端类库(require即可,使用原生template)
      zepto、underscore、arttemplate。

    一个方案:
    .coupon-container {
    padding: 1.5rem 1.5rem 5.8rem;
    background: #dff3cf url(http://fed.static.qyer.com/project/m/lm/coupon/images/bg.jpg) center bottom no-repeat;
    background-size: 100% auto;
    min-height:calc(100vh - 44px);
    }

    问题:

     什么场景下使用vh、vm、vmin、vmax会有飞一样的感觉?
    

    推荐阅读资料:
    http://www.css88.com/book/css/css3-quicksearch.htm
    http://www.zhangxinxu.com/wordpress/2012/09/new-viewport-relative-units-vw-vh-vm-vmin/
    http://javascript.ruanyifeng.com/htmlapi/requestanimationframe.html
    http://www.w3.org/TR/2014/REC-html5-20141028/

    input border IE6 bug

    border:none;与border:0;的区别体现有两点:一是理论上的性能差异二是浏览器兼容性的差异。

    1.性能差异
    【border:0;】把border设为“0”像素虽然在页面上看不见,但按border默认值理解,浏览器依然对border-width/border-color进行了渲染,即已经占用了内存值。
    【border:none;】把border设为“none”即没有,浏览器解析“none”时将不作出渲染动作,即不会消耗内存值。

    2.兼容性差异
    兼容性差异只针对浏览器IE6、IE7与标签button、input而言,在win、win7、vista 的XP主题下均会出现此情况。

    【border:none;】当border为“none”时似乎对IE6/7无效边框依然存在,如下例

    【border:0;】当border为“0”时,感觉比“none”更有效,所有浏览器都一致把边框隐藏

    总结:

    1. 对比border:0;与border:none;之间的区别在于有渲染和没渲染,感觉他们和display:none;与visibility:hidden;的关系类似,而对于border属性的渲染性能对比暂时没找测试的方法,虽然认为他们存在渲染性能上的差异但也只能说是理论上。
    2. 如何让border:none;实现全兼容?只需要在同一选择符上添加背景属性即可

    对于border:0;与border:none;个人更向于使用,border:none;,因为border:none;毕竟在性能消耗没有争议,而且兼容性可用背景属性解决不足以成为障碍。

    前些天,同学在群里问IE6下input的border:none;不管用。然后有以下考证过程:

    测试:

    border:none;无效

    border:none;*border:#ccc;(任意颜色)生效。

    测试兼容性,无问题。得出结论border:none;IE6不认识。

    我个人的测试:

    翻IE6默认CSS,涉及到border的有border-style: inset; border-width: 2px;于是

    border:0 none;生效。

    只写border:0;无效。顾得出第一次结论:必须对border的width和style进行全部设置方可消除IE6下的border。

    在得知*border:#ccc;也能解决问题的时候,发现我的理论并不正确。马上进行测试。首先input内有一个和其他行内属性不同的设置:zoom:1;在给其他行内属性加上zoom:1;之后进行测试发现border:none;解析正常。此时input在css设置上和其他行内属性一样,可能出现问题的地方就只存在在浏览器自身了。

    浏览器渲染一个标签的样式,可以简单看做以下步骤:浏览器根据自己的内核解析规则,先解析自身的默认CSS,再解析开发者书写的CSS,达到渲染标签的目的。可见影响有3部分,目前基本确定CSS部分没有问题,剩下的问题就出在浏览器内核部分。因此可以得出以下结论:IE6对INPUT的渲染存在bug,border:none;不被解析,当有border-width或border-color设置的时候才会令IE6去解析border-style:none;目前所遇情况都能解释。

    数据库设计5步骤

    1.确定entities及relationships

    a)设计宏观行为。你用此数据库来做什么?比如,希望管理雇员的信息。

    b)确定entities。对于一系列的行为,确定所管理信息所涉及到的主题范围。这将变成table。比如,雇用员工,指定具体部门,确定技能等级。

    c)确定relationships。看着行为,确定tables之间有何种关系。比如,在部门与雇员之间存在一种关系。给这种关系命名。

    d)细化行为。你从宏观行为开始,现在仔细检查这些行为,看有哪些行为能转为微观行为。比如,管理雇员的信息可细化为:
    ● 增加新员工
    ● 修改存在员工信息
    ● 删除调走的员工

    e)确定业务规则。看着你的业务规则,确定你要采取哪种。比如,可能有这样一种规则,一个部门有且只能有一个部门领导。这些规则将被设计到数据库的结构中。

    范例:

    ACME是一个小公司,在5个地方都设有办事处。当前,有75名员工。公司准备快速扩大规模,划分了9个部门,每个部门都有其领导。
    为有助于寻求新的员工,人事部门规划了68种技能,为将来人事管理作好准备。员工被招进时,每一种技能的专业等级都被确定。

    定义宏观行为
    一些ACME公司的宏观行为包括:
    ● 招聘员工
    ● 解雇员工
    ● 管理员工个人信息
    ● 管理公司所需的技能信息
    ● 管理哪位员工有哪些技能
    ● 管理部门信息
    ● 管理办事处信息

    确定entities及relationships
    我们可以确定要存放信息的主题领域(表)及其关系,并创建一个基于宏观行为及描述的图表。
    我们用方框来代表table,用菱形代表relationship。我们可以确定哪些relationship是一对多,一对一,及多对多。
    这是一个E-R草图,以后会细化。

    image

    细化宏观行为
    以下微观行为基于上面宏观行为而形成:
    ● 增加或删除一个员工
    ● 增加或删除一个办事处
    ● 列出一个部门中的所有员工
    ● 增加一项技能
    ● 增加一个员工的一项技能
    ● 确定一个员工的技能
    ● 确定一个员工每项技能的等级
    ● 确定所有拥有相同等级的某项技能的员工
    ● 修改员工的技能等级

    这些微观行为可用来确定需要哪些table或relationship。

    确定业务规则
    业务规则常用于确定一对多,一对一,及多对多关系。
    相关的业务规则可能有:
    ● 现在有5个办事处;最多允许扩展到10个。
    ● 员工可以改变部门或办事处
    ● 每个部门有一个部门领导
    ● 每个办事处至多有3个电话号码
    ● 每个电话号码有一个或多个扩展
    ● 员工被招进时,每一种技能的专业等级都被确定。
    ● 每位员工拥有3到20个技能
    ● 某位员工可能被安排在一个办事处,也可能不安排办事处。

    2.确定所需数据

    要确定所需数据:

    1. 确定支持数据
    2. 列出所要跟踪的所有数据。描述table(主题)的数据回答这些问题:谁,什么,哪里,何时,以及为什么
    3. 为每个table建立数据
    4. 列出每个table目前看起来合适的可用数据
    5. 为每个relationship设置数据
    6. 如果有,为每个relationship列出适用的数据

    确定支持数据

    你所确定的支持数据将会成为table中的字段名。比如,下列数据将适用于表Employee,表Skill,表Expert In。

    image

    如果将这些数据画成图表,就像:

    image

    需要注意:
    ● 在确定支持数据时,请一定要参考你之前所确定的宏观行为,以清楚如何利用这些数据。
    ● 比如,如果你知道你需要所有员工的按姓氏排序的列表,确保你将支持数据分解为名字与姓氏,这比简单地提供一个名字会更好。
    ● 你所选择的名称最好保持一致性。这将更易于维护数据库,也更易于阅读所输出的报表。
    ● 比如,如果你在某些地方用了一个缩写名称Emp_status,你就不应该在另外一个地方使用全名(Empolyee_ID)。相反,这些名称应当是Emp_status及Emp_id。
    ● 数据是否与正确的table相对应无关紧要,你可以根据自己的喜好来定。在下节中,你会通过测试对此作出判断。

    3.标准化数据

    标准化是你用以消除数据冗余及确保数据与正确的table或relationship相关联的一系列测试。共有5个测试。本节中,我们将讨论经常使用的3个。
    关于标准化测试的更多信息,请参考有关数据库设计的书籍。

    标准化格式
    标准化格式是标准化数据的常用测试方式。你的数据通过第一遍测试后,就被认为是达到第一标准化格式;通过第二遍测试,达到第二标准化格式;通过第三遍测试,达到第三标准化格式。

    如何标准格式:
    1. 列出数据
    2. 为每个表确定至少一个键。每个表必须有一个主键。
    3. 确定relationships的键。relationships的键是连接两个表的键。
    4. 检查支持数据列表中的计算数据。计算数据通常不保存在数据库中。
    5. 将数据放在第一遍的标准化格式中:
    6. 从tables及relationships除去重复的数据。
    7. 以你所除去数据创建一个或更多的tables及relationships。
    8. 将数据放在第二遍的标准化格式中:
    9. 用多于一个以上的键确定tables及relationships。
    10. 除去只依赖于键一部分的数据。
    11. 以你所除去数据创建一个或更多的tables及relationships。
    12. 将数据放在第三遍的标准化格式中:
    13. 除去那些依赖于tables或relationships中其他数据,并且不是键的数据。
    14. 以你所除去数据创建一个或更多的tables及relationships。

    数据与键
    在你开始标准化(测试数据)前,简单地列出数据,并为每张表确定一个唯一的主键。这个键可以由一个字段或几个字段(连锁键)组成。

    主键是一张表中唯一区分各行的一组字段。Employee表的主键是Employee ID字段。Works In relationship中的主键包括Office Code及Employee ID字段。给数据库中每一relationship给出一个键,从其所连接的每一个table中抽取其键产生。
    image

    将数据放在第一遍的标准化格式中
    ● 除去重复的组
    ● 要测试第一遍标准化格式,除去重复的组,并将它们放进他们各自的一张表中。
    ● 在下面的例子中,Phone Number可以重复。(一个工作人员可以有多于一个的电话号码。)将重复的组除去,创建一个名为Telephone的新表。在Telephone与Office创建一个名为Associated With的relationship。

    将数据放在第二遍的标准化格式中
    ● 除去那些不依赖于整个键的数据。
    ● 只看那些有一个以上键的tables及relationships。要测试第二遍标准化格式,除去那些不依赖于整个键的任何数据(组成键的所有字段)。
    ● 在此例中,原Employee表有一个由两个字段组成的键。一些数据不依赖于整个键;例如,department name只依赖于其中一个键(Department ID)。因此,Department ID,其他Employee数据并不依赖于它,应移至一个名为Department的新表中,并为Employee及Department建立一个名为 Assigned To的relationship。
    image

    将数据放在第三遍的标准化格式中
    ● 除去那些不直接依赖于键的数据。
    ● 要测试第三遍标准化格式,除去那些不是直接依赖于键,而是依赖于其他数据的数据。
    ● 在此例中,原Employee表有依赖于其键(Employee ID)的数据。然而,office location及office phone依赖于其他字段,即Office Code。它们不直接依赖于Employee ID键。将这组数据,包括Office Code,移至一个名为Office的新表中,并为Employee及Office建立一个名为Works In的relationship。

    image

    4.考量关系

    当你完成标准化进程后,你的设计已经差不多完成了。你所需要做的,就是考量关系。

    考量带有数据的关系
    你的一些relationship可能集含有数据。这经常发生在多对多的关系中。

    image

    遇到这种情况,将relationship转化为一个table。relationship的键依旧成为table中的键。

    考量没有数据的关系
    要实现没有数据的关系,你需要定义外部键。外部键是含有另外一个表中主键的一个或多个字段。外部键使你能同时连接多表数据。

    有一些基本原则能帮助你决定将这些键放在哪里:

    一对多 在一对多关系中,“一”中的主键放在“多”中。此例中,外部键放在Employee表中。

    image

    一对一 在一对一关系中,外部键可以放进任一表中。如果必须要放在某一边,而不能放在另一边,应该放在必须的一边。此例中,外部键(Head ID)在Department表中,因为这是必需的。

    image

    多对多 在多对多关系中,用两个外部键来创建一个新表。已存的旧表通过这个新表来发生联系。
    image

    5.检验设计

    在你完成设计之前,你需要确保它满足你的需要。检查你在一开始时所定义的行为,确认你可以获取行为所需要的所有数据:
    ● 你能找到一个路径来等到你所需要的所有信息吗?
    ● 设计是否满足了你的需要?
    ● 所有需要的数据都可用吗?
    如果你对以上的问题都回答是,你已经差不多完成设计了。

    最终设计
    最终设计看起来就像这样:

    image

    设计数据库的表属性
    数据库设计需要确定有什么表,每张表有什么字段。此节讨论如何指定各字段的属性。

    对于每一字段,你必须决定字段名,数据类型及大小,是否允许NULL值,以及你是否希望数据库限制字段中所允许的值。

    选择字段名
    字段名可以是字母、数字或符号的任意组合。然而,如果字段名包括了字母、数字或下划线、或并不以字母打头,或者它是个关键字(详见关键字表),那么当使用字段名称时,必须用双引号括起来。

    为字段选择数据类型
    SQL Anywhere支持的数据类型包括:
    整数(int, integer, smallint)
    小数(decimal, numeric)
    浮点数(float, double)
    字符型(char, varchar, long varchar)
    二进制数据类型(binary, long binary)
    日期/时间类型(date, time, timestamp)
    用户自定义类型

    关于数据类型的内容,请参见“SQL Anywhere数据类型”一节。字段的数据类型影响字段的最大尺寸。例如,如果你指定SMALLINT,此字段可以容纳32,767的整数。 INTEGER可以容纳2,147,483,647的整数。对CHAR来讲,字段的最大值必须指定。

    长二进制的数据类型可用来在数据库中保存例如图像(如位图)或者文字编辑文档。这些类型的信息通常被称为二进制大型对象,或者BLOBS。

    关于每一数据类型的完整描述,见“SQL Anywhere数据类型”。

    NULL与NOT NULL

    如果一个字段值是必填的,你就将此字段定义为NOT NULL。否则,字段值可以为NULL值,即可以有空值。SQL中的默认值是允许空值;你应该显示地将字段定义为NOT NULL,除非你有好理由将其设为允许空值。

    关于NULL值的完整描述,请见“NULL value”。有关其对比用法,见“Search conditions”。

    选择约束

    尽管字段的数据类型限制了能存在字段中的数据(例如,只能存数字或日期),你或许希望更进一步来约束其允许值。

    你可以通过指定一个“CHECK”约束来限制任意字段的值。你可以使用能在WHERE子句中出现的任何有效条件来约束被允许的值,尽管大多数CHECK约束使用BETWEEN或IN条件。

    更多信息

    有关有效条件的更多信息,见“Search conditions”。有关如何为表及字段指定约束,见“Ensuring Data Integrity”。

    例子
    例子数据库中有一个名为department的表,字段是dept_id, dept_name, dept_head_id。其定义如下:
    image

    注意每一字段都被指定为“not null”。这种情况下,表中每一记录的所有字段的数据都必填。

    选择主键及外部键
    主键是唯一识别表中每一项记录的字段。如何你的表已经正确标准化,主键应当成为数据库设计的一部分。
    外部键是包含另一表中主键值的一个或一组字段。外部键关系在数据库中建立了一对一及一对多关系。如果你的设计已经正确标准化,外部键应当成为数据库设计的一部分。

    js之事件冒泡和事件捕获

    事件——怎样使用事件以及IE和DOM事件模型之间存在哪些主要差别。

    (1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。

    IE 5.5: div -> body -> document

    IE 6.0: div -> body -> html -> document

    Mozilla 1.0: div -> body -> html -> document -> window

    (2)捕获型事件(event capturing):事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)。

    (3)DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件,但是,捕获型事件先发生。两种事件流会触及DOM中的所有对象,从document对象开始,也在document对象结束。

    DOM事件模型最独特的性质是,文本节点也触发事件(在IE中不会)。

    支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,还是事件冒泡时执行。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果。

    事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。
    事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。

    假设一个元素div,它有一个下级元素p。

      

    元素

    这两个元素都绑定了click事件,如果用户点击了p,它在div和p上都触发了click事件,那这两个事件处理程序哪个先执行呢?事件顺序是什么?

    两种模型

    以前,Netscape和Microsoft是不同的实现方式。

    Netscape中,div先触发,这就叫做事件捕获。

    Microsoft中,p先触发,这就叫做事件冒泡。

    两种事件处理顺序刚好相反。IE只支持事件冒泡,Mozilla, Opera 7 和 Konqueror两种都支持,旧版本的Opera’s 和 iCab两种都不支持 。

    事件捕获

    当你使用事件捕获时,父级元素先触发,子级元素后触发,即div先触发,p后触发。

    事件冒泡

    当你使用事件冒泡时,子级元素先触发,父级元素后触发,即p先触发,div后触发。

    W3C模型

    W3C模型是将两者进行中和,在W3C模型中,任何事件发生时,先从顶层开始进行事件捕获,直到事件触发到达了事件源元素。然后,再从事件源往上进行事件冒泡,直到到达document。

    程序员可以自己选择绑定事件时采用事件捕获还是事件冒泡,方法就是绑定事件时通过addEventListener函数,它有三个参数,第三个参数若是true,则表示采用事件捕获,若是false,则表示采用事件冒泡。

    ele.addEventListener('click',doSomething2,true)

    true=捕获

    false=冒泡

    传统绑定事件方式

    在一个支持W3C DOM的浏览器中,像这样一般的绑定事件方式,是采用的事件冒泡方式。

    ele.onclick = doSomething2

    IE浏览器

    如上面所说,IE只支持事件冒泡,不支持事件捕获,它也不支持addEventListener函数,不会用第三个参数来表示是冒泡还是捕获,它提供了另一个函数attachEvent。

    ele.attachEvent("onclick", doSomething2);

    附:事件冒泡(的过程):事件从发生的目标(event.srcElement||event.target)开始,沿着文档逐层向上冒泡,到document为止。

    事件的传播是可以阻止的:
    • 在W3c中,使用stopPropagation()方法
    • 在IE下设置cancelBubble = true;
    在捕获的过程中stopPropagation();后,后面的冒泡过程也不会发生了~
    3.阻止事件的默认行为,例如click 后的跳转~
    • 在W3c中,使用preventDefault()方法;
    • 在IE下设置window.event.returnValue = false;
    4.哇,终于写完了,一边测试一边写的额,不是所有的事件都能冒泡,例如:blur、focus、load、unload,(这个是从别人的文章里摘过来的,我没测试)。

    浏览器兼容问题分析

    浏览器兼容是前端开发人员必须掌握的一个技能,但是初入前端的同学或者其他后台web开发同学往往容易选择忽略,而形成两个极端:

      1 我最开始都是使用IE6,IE6上没问题,其它浏览器坑爹(多出现与前端后端一起搞的同学,小生2年前就这种状态,鼓励人家用ie6.。。。)

      2 我要遵循标准,我只要ff就好,IE就是坑爹的玩意,我不必去理他(小生一年前的心态。。。)

      现在看来,之前的想法都是不对的,我们诚然应该追求最新的浏览器使用最新的技术,但是渐进增强,向后兼容的**一定要有,

      因为就现在IE6在**的份额也是不容小视的。

      抛开之前的大道理,我们说点实际的问题,哪次前端面试不问兼容性问题?哪次我们又能回答的很好?反正我就没一次说好的,知不足然后能改,

      我前端时间便经过整理形成这篇文章,文章有很多不足,希望各位指正、补充,后面若是能形成一篇较全面的前端兼容文章就善莫大焉了!

      为什么会有兼容问题?

      由于市场上浏览器种类众多,而不同浏览器其内核亦不尽相同,所以各个浏览器对网页的解析就有一定出入,这也是导致浏览器兼容问题出现的主要原因,我们的网页需要在主流浏览器上正常运行,就需要做好浏览器兼容。

      使用Trident内核的浏览器:IE、Maxthon、TT;

      使用Gecko内核的浏览器:Netcape6及以上版本、FireFox;

      使用Presto内核的浏览器:Opera7及以上版本;

      使用Webkit内核的浏览器:Safari、Chrome。

      而我现在所说的兼容性问题,主要是说IE与几个主流浏览器如firefox,google等。

      而对IE浏览器来说,IE7又是个跨度,因为之前的版本更新甚慢,bug甚多。从IE8开始,IE浏览器渐渐遵循标准,到IE9后由于大家都一致认为标准很重要,可以说在兼容性上比较好了,但是在**来说,由于xp的占有率问题,使用IE7以下的用户仍然很多,所以我们不得不考虑低版本浏览器的兼容。

      对浏览器兼容问题,我一般是这样分类的,HTML,Javascript兼容,CSS兼容。 其中html相关问题比较容易处理,无非是高版本浏览器用了低版本浏览器无法识别的元素,导致其不能解析,所以平时注意一点就是。特别是HTML5增加了许多新标签,低版本浏览器有点影响时代进步啊;

      javascript兼容性问题

      在javascript中,各个浏览器基本语法差距不大,其兼容问题主要出现在各个浏览器的实现上,尤其对事件的支持有很大问题,在此我就说说我知道的几个问题。

      ① 在标准的事件绑定中绑定事件的方法函数为 addEventListener,而IE使用的是attachEvent

      ② 标准浏览器采用事件捕获的方式对应IE的事件冒泡机制(即标准由最外元素至最内元素或者IE由最内元素到最外元素)最后标准方亦觉得IE这方面的比较合理,所以便将事件冒泡纳入了标准,这也是addEventListener第三个参数的由来,而且事件冒泡作为了默认值。

      ③ 事件处理中非常有用的event属性获得亦不相同,标准浏览器是作为参数带人,而ie是window.event方式获得,获得目标元素ie为e.srcElement 标准浏览器为e.target

      ④ 然后在ie中是不能操作tr的innerHtml的

      ⑤ 然后ie日期函数处理与其它浏览器不大一致,比如: var year= new Date().getYear(); 在IE中会获得当前年,但是在firefox中则会获得当前年与1900的差值。

      ⑥ 获得DOM节点的方法有所差异,其获得子节点方法不一致。

      IE:parentElement parentElement.children Firefox:parentNode parentNode.childNodes childNodes的下标的含义在IE和Firefox中不同,Firefox使用DOM规范,childNodes中会插入空白文本节点。一般可以通过node.getElementsByTagName()来回避这个问题。

      当html中节点缺失时,IE和Firefox对parentNode的解释不同。例如:

      

    IE:input.parentNode的值为空节点 Firefox:input.parentNode的值为form 解决方法:Firefox中节点没有removeNode方法,必须使用如下方法 node.parentNode.removeChild(node)

      ⑦ 关于AJAX的实现上亦有所不同;

      就javascript来说,各大浏览器之间的差异还是不少的,但是具体我变得这里都不大关注了,因为我们开发过程中一般都会使用类库,若是不使用,都会自己积累形成一个类库,所以就js而言,兼容性问题基本解决了。

      让人头疼的CSS兼容

      因为之前对css的理解不够深入,也没有经过系统的学习,所以一度认为css是前端最难的东西,但真的学习后,才发现css真的很难。。。有很多东西啊!!!

      我觉得最让人头疼的问题还是CSS问题,因为一点点布局上的bug,可能导致整个页面的错位,在用户看来这是极不专业的。

      现在我就简要说说我对CSS兼容问题的认识: 先说点Hack的知识(真正的高手是不用Hack的,但要成为高手必须通过Hack这一关)

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    /* CSS属性级Hack */

    color:red; /* 所有浏览器可识别*/

    _color:red; /* 仅IE6 识别 */

    color:red; / IE6、IE7 识别 */

    +color:red; /* IE6、IE7 识别 */

    +color:red; / IE6、IE7 识别 */

    [color:red; /* IE6、IE7 识别 */

    color:red\9; /* IE6、IE7、IE8、IE9 识别 */

    color:red\0; /* IE8、IE9 识别*/

    color:red\9\0; /* 仅IE9识别 */

    color:red \0; /* 仅IE9识别 */

    color:red!important; /* IE6 不识别!important 有危险*/

    /* CSS选择符级Hack */

    html #demo { color:red;} / 仅IE6 识别 */

    +html #demo { color:red;} / 仅IE7 识别 */

    body:nth-of-type(1) #demo { color:red;} /* IE9+、FF3.5+、Chrome、Safari、Opera 可以识别 */

    head:first-child+body #demo { color:red; } /* IE7+、FF、Chrome、Safari、Opera 可以识别 */

    :root #demo { color:red\9; } : /* 仅IE9识别 */

    /* IE条件注释Hack */

      接下来说说一些我知道的BUG:

      ① css盒模型在IE6下解析有问题,我们知道就width来说,一个块级元素的magin、padding、boder,width7个属性的宽度之和,应该等于其父级元素的内容区域(width),而我们一般设置宽度若是未达到其长度,浏览器就会重置margin-right的值,将之它们的和等于其值,当然若是我们为margin设置负值,那么元素的width可能超出其父元素。

      在标准下,width为padding所占区域,但是再ie6中设置width后,其真实width为所设width-其padding与border*2,我一般采用CSShack技术处理

      ② IE6的双倍边距BUG,在块级元素浮动后本来外边距10px,但IE解释为20px,解决办法是加上display: inline

      问题:在IE6下如果某个标签使用了float属性,同时设置了其外补丁“margin:10px 0 0 10px”可以看出,上边距和左边距同样为10px,但第一个对象距左边有20px。

      解决办法:当将其display属性设置为inline时问题就都解决了。

      说明:这是因为块级对象默认的display属性值是block,当设置了浮动的同时,还设置了它的外边距 就会出现这种情况。

      也许你会问:“为什么第二个对象和第一个对象之间就不存在双倍边距的BUG”?

      因为浮动都有其相对应的对象,只有相对于其父对象的浮动 对象才会出现这样的问题。

      第一个对象是相对父对象的,而第二个对象是相对第一个对象的,所以第二个对象在设置后不会出现问题。

      另外在一些特殊布局中,可能需要组合使用display:block;和display:inline;才能达到预期效果。

      当然最坏的情况下,我们就可以使用”margin:10px 0 0 10px;*margin:10px 0 0 10px;_margin:10px 0 0 5px”,

      这种“标准属性;*IE7识别属性;_IE6识别属性”HACK方式解决

      总结:这个现象仅当块级对象设置了浮动属性后才会出现,内联对象(行级对象)不会出现此问题。并且只有设置左边距和右边距的值才会出问题,上下边距不会出现问题。

    1
    2
    3
    4

      margin双布局可以说是IE6下经典的bug之一。产生的条件是:block元素+浮动+margin。

      还记得我自认为会css的那个阶段,这个问题我经常碰到,会很熟练的用hack解决这个问题,当时还自以为是,洋洋得意。现在看来,当时的自己嫩的就像个 豆芽菜。

      真正css厉害的人基本上是不会碰到这个bug的,如果您时不时遇到这个bug,说明您的css还有好一段路要走。

      我的体会是越少的浮动,就会越少的代码,会有更灵活的页面,会有扩展性更强的页面。这不多说,归结为到一定水平了,浮动会用的较少。

      另外,您也会避免使用浮动+margin的用法。所以,越后来越不易遇到这种bug。

      这里提一下解决方法,使用hack我是不推荐的,使用hack属于比初学者稍高一点的层次水平。一个页面,没有一个hack,但是各个浏览器下表现一致,这才是水平。

      使用display:inline;可以解决这个问题。

      而为什么display:inline可以解决这个双边距bug,首先是inline元素或inline-block元素是不存在双边距问题的。

      然后,float:left等浮动属性可以让inline元素haslayout,会让inline元素表现得跟inline-block元素的特性一样, 支持高宽,垂直margin和padding等,所以div class的所有样式可以用在这个display inline的元素上。

      以上便是我所记得的一些bug,在这里我再顺带提一下haslayout(IE8废弃该属性)。

      在IE低版本浏览器时基本是表格布局的时代,几乎是所有的元素(除内联元素)都是一个盒子,内容不会超过表格的单元格,表格的单元格也不会超出表格。

      在IE6推出后,CSS改变这一假设——因为CSS允许内容超出元素。 因此haslayout这个属性就诞生了。

      在IE6,IE7中,每个元素都有haslayout这个属性,可以设置为 true 或者 false。

      如果设置为true,元素就必须去自我布局和渲染,因此元素会扩展去包含它溢出的内容,例如浮动或没截断的单词。

      如果haslayout 没有被设置成true,那么元素需依靠某个祖先元素来渲染它。这就是很多的ie bugs诞生的地方。IE浏览器下的很多bug都是haslayout = false 引起的,

      layout元素有以下特点:

      拥有布局(haslayout=true)元素不会收缩,所以可能会发生文字截断、消失的现象;

      布局元素对浮动自动清理;

      相对定位的元素没有布局,这可能导致绝对元素定位偏差;

      拥有布局的元素外边距不叠加;

      滚动时,页面会有所跳动;

      边框消失

      像素偏差

      haslayout不是一个CSS属性,所以我们不能这样的来设置它 haslayout:true;

      一个元素被设置成haslayout:true将被渲染成一个 having haslayout,

      反之同理。 一些元素本身该属性为true,若是需要触发,最好的方法是设置其zoom属性; 哪些元素本身就 haslayout:true

      ,

    , ,
    , <iframe>, (non-standard element),

      ,


    , , , <textarea>, ,   zoom:1,被认为是最好的触发Layout的方法,因为它对当前元素没有影响。 触发haslayout,相对来说比haslayout=false要简单。   以下属性和值将给定一个元素进行布局   position: absolute float: left or right display: inline-block;width: any value other than auto;   height: any value other than auto;zoom: any value other than normal (*);writing-mode: tb-rl   最后,因为各个浏览器对一些元素的默认值设置不一致也会导致表现差异,比如浏览器默认字体,默认行高,默认间距等。所以我们一般会为几个主要元素设置默认值。   结语   以上便是我对浏览器兼容的简单认识,但是还是有很多不足的地方,由于技术所限,这里提出来和各位高手交流,希望在交流学习中和以后工作中积累相关经验,做出满足主流浏览器的网页。

    前端开发工程师应知应会之网页渲染

    现今我很关注网页渲染,及其在web开发中的重要性。虽然很多文章都曾谈到这一主题,但大多是分散和割裂的。譬如,为了对这个主题有更全面的认识,我必须去搜索很多的信息来源,这也是我决定写这篇文章的原因。我相信本篇文章会有益于初级开发者,当然对希望能够更新和整理已有知识的中高级开发者同样能够有所裨益。

    当页面布局定义完成后,页面渲染的过程与样式和脚本所承担的重要角色一样,也需要在初期就开始进行优化。专业的开发者需要了解这些技巧以避免性能的问题。

    本篇文章并不会详细介绍浏览器的内部工作机制,但将会提供一些通用的规则。这是由于不同的浏览器引擎有着不同的工作方式,太针对与某一个特定浏览器的研究会使这个过程变得过于复杂。

    浏览器如何渲染网页?

    首先概述浏览器渲染网页的过程:

     1、文档对象模型(Document Object Model = DOM)将首先从来自于服务器的HTML中生成。
    
     2、加载并解析样式,形成样式对象模型(CSS Object Mode = CSSOM)。
    
     3、在DOM和CSSOM上层,创建一个渲染树,这是由将被渲染的对象形成的集合(webkit内核称这些对象为“渲染者”或“渲染对象”,在Gecko内核中则称为“帧”)。渲染树会影响DOM结构,但隐藏元素则不在此列(例如<head>标签,或具有display:none属性的元素)。在渲染树中的每个文本字符串都被表述为一个单独的渲染对象,而每个渲染对象都将包含其应有的DOM结构(或文本块)以及计算后的样式。从另一个角度上说,这个渲染树描述了DOM中的可见表征。
    
     4、计算渲染树中元素的坐标,从而成为“层”。浏览器使用一系列方法(这一系列方法仅需要一个节拍(pass))来放置所有的元素(表格需要多个节拍)。
    
     5、最后,页面将在浏览器窗口中显示出来,这个过程称为“绘制”。
    
     当用户与页面交互时,或者脚本改变页面时,前面提及的这些操作都会重复执行,页面布局改变时同样如此。
    

    重绘

    当改变了元素样式,而这个变动并不会影响元素在页面中的位置时(例如background-color,border-color,visibility),浏览器会依据新的样式仅重绘这个元素(即重绘和重新应用样式会发生)

    重新布局

    当改变影响了文档内容、结构、或元素位置时,布局会重新应用和生成。这些改变通常由以下行为触发:

    • DOM操作(元素的添加、删除、修改以及调整顺序)
    • 内容变更,包括表单域中的文字修改
    • CSS属性的计算和修改
    • 样式表的添加和移除
    • class属性的修改
    • 浏览器窗口变动(大小、滚动)
    • 伪类激活(:hover)

    如何优化浏览器渲染

    浏览器会尽可能的将重绘和重排限制在受影响的元素区域内。例如,对一个绝对定位/悬浮定位的元素尺寸大小的变更会仅仅影响这个元素及他的后代,然而一个静态定位元素的尺寸变化会让在其之后的所有元素都触发重新布局。

    另一个优化的技巧是,当运行javascript代码时,浏览器会缓存这些变更,然后在代码运行之后,将变更放到一个单独的节拍中再应用。例如,下面的代码会仅触发一次重绘和重新布局。

    var $body = $('body');

    $body.css('padding', '1px'); // 重排, 重绘

    $body.css('color', 'red'); // 重绘

    $body.css('margin', '2px'); // 重排,重绘

    // 以上步骤下实际仅发生一次重排和重绘

    但是就像上面提到的,重新计算一个元素属性将会触发一次强制的重新布局。当我们添加额外一行代码来获取元素属性时,将会产生一次强制重排

    var $body = $('body');

    $body.css('padding', '1px');

    $body.css('padding'); //获取属性,强制重排

    $body.css('color', 'red');

    $body.css('margin', '2px');

    最终,我们将造成两次重排而并非只是一次。正因如此,你需要将获取元素属性归到一次,来优化性能。(来看示例)

    当你不得不触发强制重绘时,会有一些状况发生。例如:我们将要把一条相同的属性两次应用到一个相同的元素上。最初,这个元素会以无动画的方式设为100px,然后需要带动画的调整为50px。你可以通过这个示例研究,但我会更详细的描述这个情况。

    我们首先创建一个具有transition属性的css类

    .has-transition {

    -webkit-transition: margin-left 1s ease-out;

      -moz-transition: margin-left 1s ease-out;
    
        -o-transition: margin-left 1s ease-out;
    
           transition: margin-left 1s ease-out;
    

    }

    然后进行以下处理:

    // 具有has-transition类的元素

    var $targetElem = $('#targetElemId');

    //移除has-transition类

    $targetElem.removeClass('has-transition');

    // 在css类不再存在后,改变这个属性确认动画已经去除

    $targetElem.css('margin-left', 100);

    // 增加has-transition类

    $targetElem.addClass('has-transition');

    // 修改属性

    $targetElem.css('margin-left', 50);

    这个实现并不会像期望的方式工作。这些改变被缓存起来,并会在最后的代码块中应用。因为我们需要一个强制的重排,通过以下方式可以实现:

    //移除has-transition类

    $(this).removeClass('has-transition');

    //修改属性

    $(this).css('margin-left', 100);

    // 触发强制重排,从而在class和属性中的改变可以立刻生效

    $(this)[0].offsetHeight;
    // 示例,其他的属性也可以实现

    // 增加has-transition类
    $(this).addClass('has-transition');

    // 修改属性
    $(this).css('margin-left', 50);

    现在将会按设想中的工作了。

    实际开发中的优化建议

    通过总结一些有用的信息,(作者)提供以下建议:

    • 创建有效的html和css,但不要忘记明确文档编码。样式可以添加到中,脚本则添加到的尾部。
    • 尝试简化和优化css选择器(使用CSS预处理的开发者通常不会注意这种优化方法),尽量保持低级的css嵌套。这也是css选择器标识性能的方法(从最快的那个开始)。
      • 1、标识符 #id

      • 2、类 .class

      • 3、标签: div

      • 4、兄弟选择器:a+i

      • 5、邻接父子节点选择器 ul > li

      • 6、通用选择器:*

      • 7、特性选择器:input[type="text"]

      • 8、伪类和伪元素:a:hover。你需要记住,浏览器处理CSS选择器的顺序是从右至左,这就是为什么最右边的选择器应当是最快的那种,比如#id或.class

        div * {...} 坏
        .list li {...} 坏
        .list-item {...} 好
        #list .list-item {...} 好

    1、在你的脚本中,尽可能的减少对dom的操作,尽量缓存那些会需要重复用到类型和对象。在执行复杂的操作时,比较好的方法是:操作一个“离线”的元素,并在结束后重新增加到DOM树中(离线的元素即脱离了DOM后在内存中保存的元素)。

    2、如果使用jQuery来选择元素,遵循jQuery 选择器优化实践。

    3、为了修改元素的样式,修改元素的"class"属性是通常会采用的方法。执行这种操作的DOM节点的层次越深越好。(同时也是由于深层次定义有利于逻辑解耦)

    4、如果可以的话,仅对那些绝对定位或悬浮定位的元素执行动画。

    5、滚动时去除复杂的伪元素动画(例如:hover,可以给body增加一个额外的没有hover动画的样式)。

    若需要更详细的说明,请参见以下文章:

    1. How browsers work
    2. Rendering: repaint, reflow/relayout, restyle

    希望本文能够有所启发!

    30th June 2014

    网页设计之内容、结构、表现分离

    对于初学者,我们常看见web标准的好处之一是“能做到表现和结构相分离”,那这到底是什么意思呢?我将以一个实际的例子来详细说明。首先我们必须先明白一些基本的概念:内容、结构、表现和行为。

    1.内容

    内容就是页面实际要传达的真正信息,包含数据、文档或者图片等。注意这里强调的“真正”,是指纯粹的数据信息本身。比如一个不包含辅助的信息,比如导航菜单、装饰性图片等。举个例子,有下面一段文本是我们页面要表现的信息。

    忆江南(1)唐.白居易江南好,风景旧曾谙。(2)日出江花红胜火,春来江水绿如 蓝,(3)能不忆江南。作者介绍772-846 ,字乐天,太原(今属山西)人。唐德宗朝进士,元和三年(808)拜左拾遗,后贬江州(今属江西)司马,移忠州(今属四川)刺史,又为苏州(今属江苏)、 同州(今属陕西大荔)刺史。晚居洛阳,自号醉吟先生、香山居士。其诗政治倾向鲜明,重讽喻,尚坦易,为中唐大家。也是早期词人中的佼佼者,所作对后世影响 甚大。注释(1)据《乐府杂录》,此词又名《谢秋娘》,系唐李德裕为亡姬谢秋娘作。又名《望江南》、《梦江南》等。分单调、双调两体。单调二十七字,双凋 五十四字,皆平韵。(2)谙(音安):熟悉。(3)蓝:蓝草,其叶可制青绿染料。品评此词写江南春色,首句“江南好”,以一个既浅切又圆活的“好”字,摄 尽江南春色的种种佳处,而作者的赞颂之意与向往之情也尽寓其中。同时,唯因“好”之已甚,方能“忆”之不休,因此,此句又已暗逗结句“能不忆江南”,并与 之相关阖。次句“风景旧曾谙”,点明江南风景之“好”,并非得之传闻,而是作者出牧杭州时的亲身体验与亲身感受。这就既落实了“好”字,又照应了“忆” 字,不失为勾通一篇意脉的精彩笔墨。三、四两句对江南之“好”进  行形象化的演绎,突出渲染江花、江水红绿相映的明艳色彩,给人以光彩夺目的强烈印象。其中,既有同色间的相互烘托,又有异色间的相互映衬,充分显示了作 者善于著色的技巧。篇末,以“能不忆江南”收束全词,既托出身在洛阳的作者对江南春色的无限赞叹与怀念,又造成一种悠远而又深长的韵味,把读者带入余情摇 漾的境界中。

    2.结构(Structure)

    可以看到上面的文本信息本身已经完整。但是混乱一团,难以阅读和理解,我们必须给它格式化一下。把它分成标题、作者、章、节、段落和列表等。

    标题 忆江南(1)
    作者 唐.白居易
    正文
    江南好,风景旧曾谙。(2)
    日出江花红胜火,春来江水绿如蓝,(3)
    能不忆江南。
    节1作者介绍
    772-846 ,字乐天,太原(今属山西)人。唐德宗朝进士,元和三年(808)拜左拾遗,后贬江州(今属江西)司马,移忠州(今属四川)刺史,又为苏州(今属江苏)、 同州(今属陕西大荔)刺史。晚居洛阳,自号醉吟先生、香山居士。其诗政治倾向鲜明,重讽喻,尚坦易,为中唐大家。也是早期词人中的佼佼者,所作对后世影响 甚大。
    节2注释
    列表
    (1) 据《乐府杂录》,此词又名《谢秋娘》,系唐李德裕为亡姬谢秋娘作。又名《望江南》、《梦江南》等。分单调、双调两体。单调二十七字,双凋五十四字,皆平韵。
    (2)谙(音安):熟悉。
    (3)蓝:蓝草,其叶可制青绿染料。
    节3品评
    此 词写江南春色,首句“江南好”,以一个既浅切又圆活的“好”字,摄尽江南春色的种种佳处,而作者的赞颂之意与向往之情也尽寓其中。同时,唯因 “好”之已甚,方能“忆”之不休,因此,此句又已暗逗结句“能不忆江南”,并与之相关阖。次句“风景旧曾谙”,点明江南风景之“好”,并非得之传闻,而是 作者出牧杭州时的亲身体验与亲身感受。这就既落实了“好”字,又照应了“忆”字,不失为勾通一篇意脉的精彩笔墨。三、四两句对江南之“好”进  行形象化的演绎,突出渲染江花、江水红绿相映的明艳色彩,给人以光彩夺目的强烈印象。其中,既有同色间的相互烘托,又有异色间的相互映衬,充分显示了作 者善于著色的技巧。篇末,以“能不忆江南”收束全词,既托出身在洛阳的作者对江南春色的无限赞叹与怀念,又造成一种悠远而又深长的韵味,把读者带入余情摇 漾的境界中。

    类似上面标题、作者、章、节、段落和列表,我们就把它称做结构。结构使内容更加具有逻辑性,易用性。

    2.表现(Presentation)

    虽然定义了结构,但是内容还是原来的样式没有改变,例如标题字体没有变大,正文的颜色也没有变化,没有背景,没有修饰。所有这些用来改变内容外观的东西,我们称之为“表现”。下面是对上面文本用表现处理过后的效果:

    忆江南(1)
    唐.白居易
    江南好,风景旧曾谙。(2)
    日出江花红胜火,春来江水绿如蓝,(3)
    能不忆江南。
    作者介绍
    772-846 ,字乐天,太原(今属山西)人。唐德宗朝进士,元和三年(808)拜左拾遗,后贬江州(今属江西)司马,移忠州(今属四川)刺史,又为苏州(今属江苏)、 同州(今属陕西大荔)刺史。晚居洛阳,自号醉吟先生、香山居士。其诗政治倾向鲜明,重讽喻,尚坦易,为中唐大家。也是早期词人中的佼佼者,所作对后世影响 甚大。

    注释
    (1)据《乐府杂录》,此词又名《谢秋娘》,系唐李德裕为亡姬谢秋娘作。又名《望江南》、《梦江南》等。分单调、双调两体。单调二十七字,双凋五十四字,皆平韵。
    (2)谙(音安):熟悉。
    (3)蓝:蓝草,其叶可制青绿染料。
    品评
    此词写江南春色,首句“江南好”,以一个既浅切又圆活的“好”字,摄尽江南春色的种种佳处,而作者的赞颂之意与向往之情也尽寓其中。同时,唯因 “好”之已甚,方能“忆”之不休,因此,此句又已暗逗结句“能不忆江南”,并与之相关阖。次句“风景旧曾谙”,点明江南风景之“好”,并非得之传闻,而是 作者出牧杭州时的亲身体验与亲身感受。这就既落实了“好”字,又照应了“忆”字,不失为勾通一篇意脉的精彩笔墨。三、四两句对江南之“好”进  行形象化的演绎,突出渲染江花、江水红绿相映的明艳色彩,给人以光彩夺目的强烈印象。其中,既有同色间的相互烘托,又有异色间的相互映衬,充分显示了作 者善于著色的技巧。篇末,以“能不忆江南”收束全词,既托出身在洛阳的作者对江南春色的无限赞叹与怀念,又造成一种悠远而又深长的韵味,把读者带入余情摇 漾的境界中。

    噢,很明显,我们加了2种背景,将标题字体变大并居中,将小标题加粗并变成红色,等等等等。所有这些,都是“表现”的作用。它使你的内容看上去漂 亮、可爱多了!形象一点的比喻:内容是模特,结构标明头和四肢等各个部位,表现则是服装,将模特打扮得漂漂亮亮。(请原谅我用模特打比方,很多时候模特比 web标准更具有吸引力。)

    那么行为是什么?

    3.行为(Behavior)

    行为就是对内容的交互及操作效果。例如,我们最熟悉不过的JavaScript。使用JavaScript我们可以使内容动起来,可以判断一些表单提交,可以相应你的一些操作。这个我就不再举例子了。

    所有HTML和XHTML页面就是由“结构、表现和行为”这三方面组成的。抽象一点理解,内容是基础层,然后是附加上去结构层和表现层,作后再对它们做点“行为”,示意草图如下:

    Web标准:理解表现和结构相分离_**教程网

    4.传统的HTML方法

    传统的HTML3.2/4.0标签里既有控制结构的标签,例如<title>,

    ,又有控 制表现的标签,例如,,还有本意用于结构后来被滥用于控制表现的标签,例 如:

    ,等。结构标签与表现标签混杂在一起。

    例如上面举例的页面,你可能很熟练的2-5个表格来控制边框、背景和文本居中; 用

    来定义标题和小节标题;用和来控制字体大小、颜色和粗体。轻而易 举地就能制作好页面。聪明些的设计师还采用CSS样式表来统一控制一些字体的表现。下面的代码是我们最熟悉不过的了:

    < /table>

    传统的方法看上去并没有什么问题。(我们已经很习惯了,从来没有想过会有什么问题。)但是既然W3C放弃HTML,推荐XHTML和XML就一定有它的道理和原因,问题出在哪里?

    问题就出在结构层和表现层混杂在一起!当我们只发布一些简单页面,没什么影响。当我们发布了大量页面,问题就来了。

    第一个问题是:如何改版。假如由于某些原因我们需要把背景替换成黑色,边框变成1px黄色,文字变成白色,所有文字居中。你可能就要一页一页的修改。好,你说你用了CSS,那么恭喜你,你可以直接修改样式表,轻松实现这样简单的改版。(复杂改版暂且不提。)

    第二个问题是:数据的利用。本质上讲所有页面信息都是数据。当我发布了唐诗300首,宋词100首,就是一个可观的数据 库,这个应该不难理解。那么好,是数据就存在数据查询,处理和交换的问题。假如我所有的页面上都不需要显示“品评”这一小节;假如我要将页面数据转成 excel格式;假如我要打印一个干净内容的页面(不要背景、导航、版权等不相干信息)怎么办?传统的解决方法是:一页一页删除“品评”小节;一页一页地 拷贝粘贴到excel,一页一页地制作"打印友好页"。这样做显然不是有效率的办法。

    实际上,第一个问题实质是批量改变"表现"。由于传统HTML方法的结构并不明显,甚至可以视作只有表现,我们就象设计 时尚杂志那样精心画出每一页。严谨的设计师可以控制到每1px的细节。内容与表格紧密的嵌套、混杂在一起,结构只是用表现来表现出来,而不是用标签。这种 设计方法下,任何内容的变化,结构的变化都会影响整个页面的表现,都需要一点一点细节的修改。CSS的出现,一开始似乎就是用来解决"批量改表现"的问 题。大部分的网页设计师已经能够熟练使用CSS来控制字体的大小颜色,超链接的效果,表格的边框等等,已经体会到CSS批量改变表现的效率。

    第二个问题则是无法避免。由于结构和表现混杂在一起(内容被n层的表格拆分),你无法判断哪个td里面到那个td是你需 要的数据,无法剥离其中夹杂的的标签。上例中,从哪里开始是正文?哪里开始是“品评”小节?哪些是附加信息不 需要打印?我们都无法让电脑自己去判断,唯一的方法是人工判断,手工处理。结构和表现混杂在一起,页面就好比是一张图片,你无法让电脑搜索其中的文字。 (哦,我听见有人说:我的站点有全文检索啊。恩,我想说的是,第一,这样的检索效率非常低,你需要滤过整个内容,匹配到你的"检索关键字",例如,我要查 找作者李白,搜索引擎会检索页面所有文字才能告诉你这页里面含有"李白",而且不一定出现在作者上。第二,这样的检索对数据处理和交换毫无用处。例如我要 将所有作者李白的诗摘出来,我要给所有作者增加一个肖像图片,这样的搜索毫无帮助。)

    对于第二个问题,要如何解决呢?解决的办法就是:结构清晰化,将内容、结构与表现相分离。

    5.web标准推荐的方法

    对于内容、结构与表现相分离,最早是在软件开发架构理论中提出来的。QQ用过吧,QQ面板的变更皮肤就是内容不变,外观 表现在变化;还有 winamp的skin也是这种原理的典型体现。其实我们大多数的设计师已经在实践中都接触到。我们的动态信息发布系统,实际上就是基于这个原理制作的, 设计师只需要设计模版,程序员将数据(标题、作者、发布日期、摘要、相关文章、相关图片等等)从数据库中读出,嵌入你的模板,形成一个新的页面再展示给浏 览者。其中的内容已经被结构化后分别保存在数据库的不同字段中。例如查找作者,我们只要在作者字段中搜索,这样的效率就提高很多了。

    上面都是有赖于程序,如果页面文档本身就能实现表现和结构相分离,那么数据的交换和再利用不就更方便了。嘿嘿,其实 XML就是奔着这个方向去的,XML允许你自己定制结构标识,还提供了XSLT用来格式化、查询和处理文档内容。例如上面的诗词页面,用XML写出来的代 码就象这样:

    <标题>忆江南</标题>
    <作者>唐.白居易</作者>
    <正文>江南好...</正文>
    <作者介绍>772-846 ,字乐天...</作者介绍>
    <注释>据《乐府杂录》...</注释>
    <品评>此词写江南春色...</品评>

    这些<标题><作者>都是自己定义的标签,这样文档结构非常清晰,查询和处理也很简单。啊哦,说远了。还是回到目前能应用的web标准方法上。

    web标准方法目前推荐大家使用XHTML+CSS来制作网站。目标是使结构与表现彻底相分离。

    就是说,XHTML 的标签只用来定义文档的结构, 所有涉及表现的东西通通剥离出来,把它放到一个单独的文件里,这个单独的文件就是CSS。(CSS的好处上面已经讲到,可以批量处理表现)。采用这种方法 后,上面的第二个问题中的3个假设困难就迎刃而解。我们可以利用样式表将所有"品评"结构不显示 (DISPLAY: none);我们可以根据页面结构标签将内容自动导入到excel;我们可以设计一个专门的打印样式表,隐藏掉所有附加的信息,只打印干净的内容。就这么 简单。

    现在你明白了吧,为什么我们反对用表格设计布局。原因是

    忆江南

    用于布局的时候,它是一个控制表现的标签。混杂在内容和结构中,使我们的内容数据无法再利用。结构与表现相分离带来的好处主要有:

    1.数据的多样显示。通过不同的样式表适应不同的设备,做到内容与设备无关

    2.保持整个站点的视觉一致性变得非常简单,修改样式表就可以轻松改版;

    3.由于结构清晰,数据的集成、更新和处理更加方便灵活;

    4.更有意义的搜索。

    IE6兼容性问题及IE6常见bug详细汇总

    1、终极方法:条件注释

    缺点是在IE浏览器下可能会增加额外的HTTP请求数。

    2、CSS选择器区分
    IE6不支持子选择器;先针对IE6使用常规申明CSS选择器,然后再用子选择器针对IE7+及其他浏览器。

    复制代码
    代码如下:

    /* IE6 专用 /
    .content {color:red;}
    /
    其他浏览器 */
    div>p .content {color:blue;} -->

    3、PNG半透明图片的问题
    虽然可以通过JS等方式解决,但依然存在载入速度等问题,所以,这个在设计上能避免还是尽量避免为好。以达到网站最大优化。
    4、IE6下的圆角
    IE6不支持CSS3的圆角属性,性价比最高的解决方法就是用图片圆角来替代,或者放弃IE6的圆角。

    5、IE6背景闪烁
    如果你给链接、按钮用CSS sprites作为背景,你可能会发现在IE6下会有背景图闪烁的现象。造成这个的原因是由于IE6没有将背景图缓存,每次触发hover的时候都会重新加载,可以用JavaScript设置IE6缓存这些图片:

    复制代码
    代码如下:

    document.execCommand("BackgroundImageCache",false,true);

    6、最小高度
    IE6 不支持min-height属性,但它却认为height就是最小高度。解决方法:使用ie6不支持但其余浏览器支持的属性!important。

    复制代码
    代码如下:

    container {min-height:200px; height:auto !important; height:200px;}

    7、最大高度

    复制代码
    代码如下:

    //直接使用ID来改变元素的最大高度
    var container = document.getElementById('container');
    container.style.height = (container.scrollHeight > 199) ? "200px" : "auto";
    //写成函数来运行
    function setMaxHeight(elementId, height){
    var container = document.getElementById(elementId);
    container.style.height = (container.scrollHeight > (height - 1)) ? height + "px" : "auto";
    }
    //函数示例
    setMaxHeight('container1', 200);
    setMaxHeight('container2', 500);

    8、100% 高度
    在IE6下,如果要给元素定义100%高度,必须要明确定义它的父级元素的高度,如果你需要给元素定义满屏的高度,就得先给html和body定义height:100%;。

    9、最小宽度
    同max-height和max-width一样,IE6也不支持min-width。

    复制代码
    代码如下:

    //直接使用ID来改变元素的最小宽度
    var container = document.getElementById('container');
    container.style.width = (container.clientWidth < width) ? "500px" : "auto";
    //写成函数来运行
    function setMinWidth(elementId, width){
    var container = document.getElementById(elementId);
    container.style.width = (container.clientWidth < width) ? width + "px" : "auto";
    }
    //函数示例
    setMinWidth('container1', 200);
    setMinWidth('container2', 500);

    10、最大宽度

    复制代码
    代码如下:

    //直接使用ID来改变元素的最大宽度
    var container = document.getElementById(elementId);
    container.style.width = (container.clientWidth > (width - 1)) ? width + "px" : "auto";
    //写成函数来运行
    function setMaxWidth(elementId, width){
    var container = document.getElementById(elementId);
    container.style.width = (container.clientWidth > (width - 1)) ? width + "px" : "auto";
    }
    //函数示例
    setMaxWidth('container1', 200);
    setMaxWidth('container2', 500);

    11、双边距Bug
    当元素浮动时,IE6会错误的把浮动方向的margin值双倍计算。个人觉得较好解决方法是避免float和margin同时使用。

    12、清除浮动
    如果你想用div(或其他容器)包裹一个浮动的元素,你会发现必须给div(容器)定义明确的height、width、overflow之中一个属性(除了auto值)才能将浮动元素严实地包裹。

    复制代码
    代码如下:

    container {border:1px solid #333; overflow:auto; height:100%;}

    floated1 {float:left; height:300px; width:200px; background:#00F;}

    floated2 {float:right; height:400px; width:200px; background:#F0F;}

    更多:http://www.twinsenliang.net/skill/20090413.html

    13、浮动层错位
    当内容超出外包容器定义的宽度时,在IE6中容器会忽视定义的width值,宽度会错误地随内容宽度增长而增长。
    浮动层错位问题在IE6下没有真正让人满意的解决方法,虽然可以使用overflow:hidden;或overflow:scroll;来修正, 但hidden容易导致其他一些问题,scroll会破坏设计;JavaScript也没法很好地解决这个问题。所以建议是一定要在布局上避免这个问题发 生,使用一个固定的布局或者控制好内容的宽度(给内层加width)。

    14、躲猫猫bug
    在IE6和IE7下,躲猫猫bug是一个非常恼人的问题。一个撑破了容器的浮动元素,如果在他之后有不浮动的内容,并且有一些定义了:hover的链接,当鼠标移到那些链接上时,在IE6下就会触发躲猫猫。
    解决方法很简单:
    1.在(那个未浮动的)内容之后添加一个
    2.触发包含了这些链接的容器的hasLayout,一个简单的方法就是给其定义height:1%;

    15、绝对定位元素的1像素间距bug
    IE6下的这个错误是由于进位处理误差造成(IE7已修复),当绝对定位元素的父元素高或宽为奇数时,bottom和right会产生错误。唯一的解决办法就是给父元素定义明确的高宽值,但对于液态布局没有完美的解决方法。

    16、3像素间距bug
    在IE6中,当文本(或无浮动元素)跟在一个浮动的元素之后,文本和这个浮动元素之间会多出3像素的间隔。
    给浮动层添加 display:inline 和 -3px 负值margin
    给中间的内容层定义 margin-right 以纠正-3px

    17、IE下z-index的bug
    在IE浏览器中,定位元素的z-index层级是相对于各自的父级容器,所以会导致z-index出现错误的表现。解决方法是给其父级元素定义z-index,有些情况下还需要定义position:relative。

    18、Overflow Bug
    在IE6/7中,overflow无法正确的隐藏有相对定位position:relative;的子元素。解决方法就是给外包容器.wrap加上position:relative;。

    19、横向列表宽度bug
    如果你使用float:left;把

  • 横向摆列,并且
  • 内包含的(或其他)触发了 hasLayout,在IE6下就会有错误的表现。解决方法很简单,只需要给定义同样的float:left;即可。

    20、列表阶梯bug
    列表阶梯bug通常会在给

  • 的子元素使用float:left;时触发,我们本意是要做一个横向的列表(通常 是导航栏),但IE却可能呈现出垂直的或者阶梯状。解决办法就是给
  • 定义float:left;而非子元素,或者 给
  • 定义display:inline;也可以解决。

    21、垂直列表间隙bug
    当我们使用

  • 包含一个块级子元素时,IE6(IE7也有可能)会错误地给每条列表元素(
  • )之间添加空隙。
    解决方法:把flaot并且清除float来解决这个问题;另外一个办法就是触发的hasLayout(如定 义高宽、使用zoom:1;);也可以给
  • 定义display:inline;来解决此问题;另外还有一个极有趣的方法,给包含的文本末尾添加一个空格。

    22、IE6中的:hover
    在IE6中,除了(需要有href属性)才能触发:hover行为,这妨碍了我们实现许多鼠标触碰效果,但还是有一些法子是可以解决它的。最好是不要用:hover来实现重要的功能,仅仅只用它来强化效果。

    23、IE6调整窗口大小的 Bug
    当把body居中放置,改变IE浏览器大小的时候,任何在body里面的相对定位元素都会固定不动了。解决办法:给body定义position:relative;就行了。

    24、文本重复Bug
    在IE6中,一些隐藏的元素(如注释、display:none;的元素)被包含在一个浮动元素里,就有可能引发文本重复bug。解决办法:给浮动元素添加display:inline;。

  • 关于javascript字符串中的“\”

    问题:

      var a = "\s";

      alert(a);

    结果是s,而不是\s。为什么?

    答案很简单,\为转义字符。那”\s"是否就等于"s"呢?

    可以认为“" + 某个固定的字母就构成了新的含义,那假如这个字母不在上述列表之列,那会如何显示呢?

    从开始的例子里看到,好像是假如+char,有值则显示为所表达的值,否则自动忽略前面的""。即”\s" == "s",由于两个也均为string类型,因此"\s" === "s"。

    验证一下,的确如此。

    跨域cookie在IE与firefox下的不同

    在使用单点登录的时候遇到了这个问题,在tuan.xxx.com下存在一个名为name的cookie,同时在.xxx.com父域下也存在同名的name的cookie。在获取cookie时,在IE和Firefox中出现了不同的结果,导致单点登录在ie下面失败,火狐下面正常。

    情况分析:
    tuan.xxx.com下的页面读取cookie的情况如下:
    1.在IE中,会将子域的cookie和父域的cookie合并在一起读出,谁在前就取那个的值,我的情况是是主域(xxx.com)在前生成,读取的就是之主域的值。
    2.在Firefox中,tuan.xxx.com子域下的页面读取cookie的情况规则相同,tuan.xxx.com子域的name优先读取。

    主要的原因是tuan.xxx.com和xxx.com使用来同样名字的cookie引起了这个问题,明白原因后,重命名了主域的cookie名称解决了问题。
    在以后的开发中要注意避免这样的问题,cookie命名前面加上前缀以示区别,避免不必要的问题产生。

    javascript的事件模型

    javascript的事件模型,采用”冒泡”模式,也就是说,子元素的事件会逐级向上”冒泡”,成为父元素的事件。

    利用这一点,可以大大简化事件的绑定。比如,有一个表格(table元素),里面有100个格子(td元素),现在要求在每个格子上面绑定一个点击事件(click),请问是否需要将下面的命令执行100次?

    $(“td”).bind(“click”, function(){

    $(this).toggleClass(“click”);

    });

    回答是不需要,我们只要把这个事件绑定在table元素上面就可以了,因为td元素发生点击事件之后,这个事件会”冒泡”到父元素table上面,从而被监听到。

    因此,这个事件只需要在父元素绑定1次即可,而不需要在子元素上绑定100次,从而大大提高性能。这就叫事件的”委托处理”,也就是子元素”委托”父元素处理这个事件。

    具体的写法有两种。第一种是采用.delegate()方法:

    $(“table”).delegate(“td”, “click”, function(){

    $(this).toggleClass(“click”);

    });

    第二种是采用.live()方法:

    $(“table”).each(function(){

    $(“td”, this).live(“click”, function(){

    $(this).toggleClass(“click”);
    });
    });

    这两种写法基本等价。唯一的区别在于,.delegate()是当事件冒泡到指定的父元素时触发,.live()则是当事件冒泡到文档的根元素后触发,因此.delegate()比.live()稍快一点。此外,这两种方法相比传统的.bind()方法还有一个好处,那就是对动态插入的元素也有效,.bind()只对已经存在的DOM元素有效,对动态插入的元素无效。

    根据测试,委托处理比不委托处理,快了几十倍。在委托处理的情况下,.delegate()又比.live()大约快26%。

    老外的前端面试题

    用Twitter吗?
    如果用,你在Twitter上面关注谁了?
    用Github吗?
    如果用,请列举几个你在上面关注的存储库(repos)。
    你关注了什么博客?
    你用过什么版本控制系统?
    你偏爱的开发环境是什么?(操作系统,编辑器,浏览器,工具等等)
    你能描述一下当你创建一张网页时的流程吗?
    你能描述一下渐进增强和平稳降级的不同之处吗?
    如果回答了“没人能描述”,则加分
    如果描述了“特征检测”,则额外加分
    解释“语义化的HTML”的意思。
    JS压缩(Minification)是作什么用的?
    为什么把站点资源文件放在多个域下的做法比较好?
    一个浏览器一次从一个域下下载几个资源?
    如果你为某个设计稿做了8个不同的css文件,你是如何把它们集成到网站当中去的?
    文件合并
    @import,除非这部分工作在构建系统里面已经做掉了
    如果你加入了一个项目,他们用tabs,而你用空格,你会怎么做?
    问题:retab! 命令
    写一个简单的幻灯片放映的页面。
    如果不用JS,则加分
    你用什么工具来测试你的代码性能?
    如果今年你能掌握一门技术,它将会是什么?
    说出3种减少页面加载时间的方法。(感觉上或者真实地减少了时间)
    解释一下标准的重要性。

    HTML细节问题:
    doctype是干嘛用的?你能说出几种来?
    标准模式和怪异模式的区别是什么?
    在用XHTML页面时有什么限制吗?
    用application/xhtml+xml?会有什么问题
    你是如何做多语言内容的页面的?
    HTML5中能使用XHTML的语法吗?在HTML5中你是怎么使用XML的?
    data- 开头的这种属性有什么好处?
    HTML4中的内容模型(content model)是什么?和HTML5中的有区别吗?
    试想HTML5为一个开发的网络平台,那HTML5的基础模块(building blocks)是什么?
    描述一下cookie,sessionStorage和localStorage的区别。

    JS细节问题:
    你用过什么JavaScript库?
    JavaScript和Java有何不同?
    未定义(undefined)和未申明(undeclared)变量分别是指什么?
    闭包(closure)是什么?如何/为什么 使用?
    你最喜欢的闭包写法是哪种?Argyle(只适用于立即调用模型(IIFEs))
    匿名函数(anonymous functions)的典型使用案例是什么?
    解释一下JavaScript 模块化模式以及你何时使用。
    提到清晰的命名空间(clean namespace),加分
    如果你的模块没有命名,那将会怎么?
    你是如何组织你的代码的?(模块模式(module pattern),类继承(classical inheritance)?)
    宿主对象(host objects)和原生对象(native objects)有何不同?
    以下语句的区别:

    function Person(){}
    var person = Person()
    var person = new Person()
    复制代码

    call 和 apply的区别?
    解释 Function.prototype.bind
    你何时优化你的代码?
    你能解释下继承在JavaScript中是如何工作的吗?
    如果说出“没人会”的有趣答案,加分
    如果他开始认真解释了,额外加分
    你何时用过document.write()?
    正确答案:1999年 – 淘汰初级开发者的时候(time to weed out the junior devs)
    特征检测(feature detection),特征推断(feature inference),用户代理(UA)字符串的区别?
    尽可能细地解释一下AJAX。
    解释一下JSONP是如何工作的?(为什么它不是真正的AJAX?)
    解释一下“提升(hoisting)”
    什么是FOUC?你是如何避免FOUC的?
    描述一下事件冒泡
    “attribute” 和 “property”的区别是?
    用过JavaScript模板吗?如果用过,那是什么模板或者是怎么用的?
    为什么扩展内置的JavaScript对象(extending built in JavaScript objects)不是一个好的主意?
    为什么扩展内置组件(extending built ins)是个不错的主意?
    document load事件和document ready事件的区别
    == 和 === 的区别是什么?
    解释一下你是如何从window的URL中获取查询字符串参数的(query string parameter)?
    解释一下关于Javascript的同源策略(same-origin policy)
    解释一下事件代理(event delegation)
    描述一下JavaScript中的继承模式
    使下面的代码工作:

    [1,2,3,4,5].duplicator(); // [1,2,3,4,5,1,2,3,4,5]
    复制代码

    解释一下Memoization的策略
    为什么叫三元(Ternary)操作符?“三元”暗示着什么?
    函数的参数数量(arity)是什么?
    

    JS代码例子:

    ~~3.14
    复制代码
    问题:上述语句的返回结果是什么?
    "i'm a lasagna hog".split("").reverse().join("");
    复制代码
    问题:上述语句的返回结果是什么?
    ( window.foo || ( window.foo = "bar" ) );
    复制代码
    问题:window.foo的值是多少
    var foo = "Hello";
    (function() {
    var bar = " World";
    alert(foo + bar);
    })();
    alert(foo + bar);
    复制代码
    问题:2个alert的输出结果是什么
    jQuery细节问题:
    解释一下“连接(chaining)”操作
    .end() 是做什么的?
    在绑定事件的时候,你是如何(为什么)加上事件的命名空间(namespace)
    效果队列(effects queue)(或者FX)是什么?
    .get(), [], .eq() 的区别
    .bind(), live()和.delegate()的区别是什么?
    $ 和 $.fn 的区别?或只说$.fn是什么?
    优化下面的选择方法:

    $(".foo div#bar:eq(0)")
    复制代码

    CSS细节问题:
    描述一下“reset”css文件的作用以及它为什么是有用的?
    描述一下浮动(Floats)及是如何工作的
    清除浮动的技术有哪些?什么场景下该用什么技术?
    解释一下CSS Sprite及你是如何在一张页面或者一个站点上面使用该技术的?
    对于功能有限的浏览器(feature-constrained browsers),你是如何制作你的页面的?
    你使用什么技术(处理)
    有什么方法在视觉层面上隐藏内容(使之仅对屏幕阅读者(screenreaders)可用)?
    你使用过栅格系统(grid system)吗?如果用过,你喜欢哪种?
    你在其它媒体或者移动设备上使用过或者实现过布局(css)吗?(Have you used or implement media queries or mobile specific layouts/CSS?)
    给SVG添加样式,熟悉吗?
    对于打印,你是如何优化你的页面的?
    在写css时有什么gotchas?(What are some of the “gotchas” for writing efficient CSS?)
    使用过LESS吗?
    网 页设计使用非标准字体的排版,你将如何实现?(避免提及网页字体(webfonts),那样的话他们会想到(你的意图))(How would you implement a web design comp that uses non-standard fonts?)
    解释一下浏览器是如何将元素和css选择器进行匹配的?

    随意有趣的问题:
    你最酷的编码作品是什么,让你自豪的是什么?
    你知道HTML5小组的标记吗?
    你现在在或者曾经在过小船上面吗?
    告诉我你最喜欢的Firebug/Webkit Inspector的功能
    你有养宠物计划吗?哪种宠物
    解释一下“cornify”的重要性
    在一张纸上,竖直写下A,B,C,D 4个字母。然后不写代码,将这些字母降序排列。
    等着看他们是否把纸给上下颠倒过来
    这是一个在面试将要结束,缓解紧张气氛的好方法,应该会有笑声:)
    海盗或是忍者:
    如果能说出好的理由做由海盗和忍者的组成物,加分(若是猴子僵尸海盗忍者,+2分)
    如果不做web开发,你会做什么?
    怪盗卡门(Carmen Sandiego)在哪个世界(提示: 他们的回答总是错的)
    你最喜欢IE的什么特性?

    CSS的inherit与auto使用分析

    一个很显浅的寓言,千年老树,电打雷劈,屹立不倒,却毁于蝼蚁的侵袭之下。自以为精通CSS的人,常常被一些小问题搞到头晕脑胀。
    通常是一个很小的数值,经过层层放大歪曲后,整个布局就走形了。CSS是一门很简单的语言,易学易用,但也最容易出垃圾代码。这是没有深入研究这门语言所致。本人认为,CSS是由以下三大块构成的:默认值,继承系统与加权系统。默认值,也就是浏览器在用户没有设置属性的情况下,默认指定的属性。CSS框架基本都有一个叫reset.css 的文件,就是对其进行重设,消除各浏览器的差异的。继承系统就是下面要重点讨论的东西。加权系统,也就是优先级的问题,不在本文的讨论范畴,不说了。另,这三个东西都面临着IE Bug的侵袭,危害甚大,自己另行了断吧(笑)。

    在CSS中,许多属性都是可以继承的,如某个段落的字体设置为白色,其元素的字体不用设置或设置为inhert,它就是白色。这些属性被称之为inherited property,它会从父元素获取对应属性的经过计算与转换的值(computed value),如果父元素和它的情形一样,它就继续往上找,最后没有就使用浏览器的默认值。

    下面是 inherited properties的一览表:
    复制代码代码如下:

    border-collapse
    border-spacing
    caption-side
    color
    cursor
    direction
    empty-cells
    font
    font-family
    font-stretch
    font-size
    font-size-adjust
    font-style
    font-variant
    font-weight
    letter-spacing
    line-height
    list-style
    opacity
    list-style-image
    list-style-type
    quotes
    text-align
    text-indent
    text-transform
    white-space
    word-spacing

    [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

    我们给父元素设置了字体的样式,没有设置子元素的,当取出子元素的时,发现其值转换为rgb格式(当然IE除外啦!)
    不过,在IE7及其之前的版本,是不支持用inhert来设置direction与visibility以外的样式属性。具体可参见这里与这里
    在IE8中,原本是inherited property的text-align在th中失效。

    Ruby Rouvre
    By 司徒正美

    table, tr, td, th {
    border-collapse: collapse;
    border: 1px solid #000;
    }
    table {
    text-align: right;
    }
    td, th {
    width: 100px;
    }
    本来th应该会从table中继承文本向右对齐的设置,但失效了……

    [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

    解决IE8这个弱智Bug也很容易,就是显式地设置inhert。
    table, tr, td, th {
    border-collapse: collapse;
    border: 1px solid #000;
    }
    table {
    text-align: right;
    }
    td, th {
    width: 100px;
    }
    th {
    text-align: inherit;
    }

    [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

    此外还有一些CSS属性是不能继承的,最经典如border系列。它被称之为non-inherited property,如果我们不为它设置,我们只能取得浏览器的默认值,默认值在火狐中被称之为 initial value 。一个相关的好消息是,默认值在火狐也可以指定了,这样我们就不用reset样式了!
    下面是non-inherited property的一览表:
    background
    border
    bottom
    clear
    display
    float
    height
    left
    margin
    outline
    overflow
    padding
    position
    right
    top
    visibility
    width
    z-index

    [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

    我们给父元素设置了背景颜色,没有设置子元素的,这时会取得浏览器的默认值transparent(W3C那一方好像只要是颜色都会转换为rgb格式,多出的a为Alpha)
    http://monc.se/kitchen/38/cascading-order-and-inheritance-in-css http://elizabethcastro.com/html/extras/cssref.html
    接着我们来看auto,这是一个含糊不清但是有长度概念的值。应用于以下属性:
    overflow
    cursor
    height
    width
    marker-offset
    margin
    margin-* (left|bottom|top|right|start|end)
    top
    bottom
    left
    right
    table-layout
    z-index
    -moz-column-width
    languages
    在块级元素的可度量的属性中(如width,height),如果不设置值,其默认值是auto,但它很容易会被父级元素的值覆盖,也就是隐式地成为了inhert了。在内联元素中,由于不具备盒子模型,如果不设置,就算是火狐也原本奉还它,这对于精确计算元素的宽度与高度是非常不利的。auto还有对称性,这个在居中布局我们常常运用到它。在非度量的属性中,如overflow,就要具体情况具体分析了。

    10种排序算法总结

    排序算法有很多,所以在特定情景中使用哪一种算法很重要。为了选择合适的算法,可以按照建议的顺序考虑以下标准:
    (1)执行时间
    (2)存储空间
    (3)编程工作
    对于数据量较小的情形,(1)(2)差别不大,主要考虑(3);而对于数据量大的,(1)为首要。
    主要排序法有:
    一、冒泡(Bubble)排序——相邻交换
    二、选择排序——每次最小/大排在相应的位置
    三、插入排序——将下一个插入已排好的序列中
    四、壳(Shell)排序——缩小增量
    五、归并排序
    六、快速排序
    七、堆排序
    八、拓扑排序
    九、锦标赛排序
    十、基数排序
    一、冒泡(Bubble)排序
    ----------------------------------Code 从小到大排序n个数------------------------------------
    void BubbleSortArray()
    {
    for(int i=1;i<n;i++)
    {
    for(int j=0;i<n-i;j++)
    {
    if(a[j]>a[j+1])//比较交换相邻元素
    {
    int temp;
    temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;
    }
    }
    }
    }
    -------------------------------------------------Code------------------------------------------------
    效率 O(n²),适用于排序小列表。
    二、选择排序
    ----------------------------------Code 从小到大排序n个数--------------------------------
    void SelectSortArray()
    {
    int min_index;
    for(int i=0;i<n-1;i++)
    {
    min_index=i;
    for(int j=i+1;j<n;j++)//每次扫描选择最小项
    if(arr[j]<arr[min_index]) min_index=j;
    if(min_index!=i)//找到最小项交换,即将这一项移到列表中的正确位置
    {
    int temp;
    temp=arr[i]; arr[i]=arr[min_index]; arr[min_index]=temp;
    }
    }
    }
    -------------------------------------------------Code-----------------------------------------
    效率O(n²),适用于排序小的列表。
    三、插入排序
    --------------------------------------------Code 从小到大排序n个数-------------------------------------
    void InsertSortArray()
    {
    for(int i=1;i<n;i++)//循环从第二个数组元素开始,因为arr[0]作为最初已排序部分
    {
    int temp=arr[i];//temp标记为未排序第一个元素
    int j=i-1;
    while (j>=0 && arr[j]>temp)/将temp与已排序元素从小到大比较,寻找temp应插入的位置/
    {
    arr[j+1]=arr[j];
    j--;
    }
    arr[j+1]=temp;
    }
    }
    ------------------------------Code--------------------------------------------------------------
    最佳效率O(n);最糟效率O(n²)与冒泡、选择相同,适用于排序小列表
    若列表基本有序,则插入排序比冒泡、选择更有效率。
    四、壳(Shell)排序——缩小增量排序
    -------------------------------------Code 从小到大排序n个数-------------------------------------
    void ShellSortArray()
    {
    for(int incr=3;incr<0;incr--)//增量递减,以增量3,2,1为例
    {
    for(int L=0;L<(n-1)/incr;L++)//重复分成的每个子列表
    {
    for(int i=L+incr;i<n;i+=incr)//对每个子列表应用插入排序
    {
    int temp=arr[i];
    int j=i-incr;
    while(j>=0&&arr[j]>temp)
    {
    arr[j+incr]=arr[j];
    j-=incr;
    }
    arr[j+incr]=temp;
    }
    }
    }
    }
    --------------------------------------Code-------------------------------------------
    适用于排序小列表。
    效率估计O(nlog2^n)~O(n^1.5),取决于增量值的最初大小。建议使用质数作为增量值,因为如果增量值是2的幂,则在下一个通道中会再次比较相同的元素。
    壳(Shell)排序改进了插入排序,减少了比较的次数。是不稳定的排序,因为排序过程中元素可能会前后跳跃。
    五、归并排序
    ----------------------------------------------Code 从小到大排序---------------------------------------
    void MergeSort(int low,int high)
    {
    if(low>=high) return;//每个子列表中剩下一个元素时停止
    else int mid=(low+high)/2;/将列表划分成相等的两个子列表,若有奇数个元素,则在左边子列表大于右侧子列表/
    MergeSort(low,mid);//子列表进一步划分
    MergeSort(mid+1,high);
    int [] B=new int [high-low+1];//新建一个数组,用于存放归并的元素
    for(int i=low,j=mid+1,k=low;i<=mid && j<=high;k++)/两个子列表进行排序归并,直到两个子列表中的一个结束/
    {
    if (arr[i]<=arr[j];)
    {
    B[k]=arr[i];
    I++;
    }
    else
    { B[k]=arr[j]; j++; }
    }
    for( ;j<=high;j++,k++)//如果第二个子列表中仍然有元素,则追加到新列表
    B[k]=arr[j];
    for( ;i<=mid;i++,k++)//如果在第一个子列表中仍然有元素,则追加到新列表中
    B[k]=arr[i];
    for(int z=0;z<high-low+1;z++)//将排序的数组B的 所有元素复制到原始数组arr中
    arr[z]=B[z];
    }
    -----------------------------------------------------Code---------------------------------------------------
    效率O(nlogn),归并的最佳、平均和最糟用例效率之间没有差异。
    适用于排序大列表,基于分治法。
    六、快速排序
    ------------------------------------Code--------------------------------------------
    /快速排序的算法**:选定一个枢纽元素,对待排序序列进行分割,分割之后的序列一个部分小于枢纽元素,一个部分大于枢纽元素,再对这两个分割好的子序列进行上述的过程。/ void swap(int a,int b){int t;t =a ;a =b ;b =t ;}
    int Partition(int [] arr,int low,int high)
    {
    int pivot=arr[low];//采用子序列的第一个元素作为枢纽元素
    while (low < high)
    {
    //从后往前栽后半部分中寻找第一个小于枢纽元素的元素
    while (low < high && arr[high] >= pivot)
    {
    --high;
    }
    //将这个比枢纽元素小的元素交换到前半部分
    swap(arr[low], arr[high]);
    //从前往后在前半部分中寻找第一个大于枢纽元素的元素
    while (low <high &&arr [low ]<=pivot )
    {
    ++low ;
    }
    swap (arr [low ],arr [high ]);//将这个枢纽元素大的元素交换到后半部分
    }
    return low ;//返回枢纽元素所在的位置
    }
    void QuickSort(int [] a,int low,int high)
    {
    if (low <high )
    {
    int n=Partition (a ,low ,high );
    QuickSort (a ,low ,n );
    QuickSort (a ,n +1,high );
    }
    }
    ----------------------------------------Code-------------------------------------
    平均效率O(nlogn),适用于排序大列表。
    此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能导致O(n²)的最糟用例效率。若数基本有序,效率反而最差。选项中间值作为枢纽,效率是O(nlogn)。
    基于分治法。
    七、堆排序
    最大堆:后者任一非终端节点的关键字均大于或等于它的左、右孩子的关键字,此时位于堆顶的节点的关键字是整个序列中最大的。
    **:
    (1)令i=l,并令temp= kl ;
    (2)计算i的左孩子j=2i+1;
    (3)若j<=n-1,则转(4),否则转(6);
    (4)比较kj和kj+1,若kj+1>kj,则令j=j+1,否则j不变;
    (5)比较temp和kj,若kj>temp,则令ki等于kj,并令i=j,j=2i+1,并转(3),否则转(6)
    (6)令ki等于temp,结束。
    -----------------------------------------Code---------------------------
    void HeapSort(SeqIAst R)
    { //对R[1..n]进行堆排序,不妨用R[0]做暂存单元 int I; BuildHeap(R); //将R[1-n]建成初始堆for(i=n;i>1;i--) //对当前无序区R[1..i]进行堆排序,共做n-1趟。{ R[0]=R[1]; R[1]=R[i]; R[i]=R[0]; //将堆顶和堆中最后一个记录交换 Heapify(R,1,i-1); //将R[1..i-1]重新调整为堆,仅有R[1]可能违反堆性质 } } ---------------------------------------Code--------------------------------------
    堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。
    堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均性能较接近于最坏性能。 由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。 堆排序是就地排序,辅助空间为O(1), 它是不稳定的排序方法。
    堆排序与直接插入排序的区别:
    直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
    堆排序可通过树形结构保存部分比较结果,可减少比较次数。
    八、拓扑排序
    例 :学生选修课排课先后顺序
    拓扑排序:把有向图中各顶点按照它们相互之间的优先关系排列成一个线性序列的过程。
    方法:
    在有向图中选一个没有前驱的顶点且输出
    从图中删除该顶点和所有以它为尾的弧
    重复上述两步,直至全部顶点均已输出(拓扑排序成功),或者当图中不存在无前驱的顶点(图中有回路)为止。
    ---------------------------------------Code--------------------------------------
    void TopologicalSort()/输出拓扑排序函数。若G无回路,则输出G的顶点的一个拓扑序列并返回OK,否则返回ERROR/
    {
    int indegree[M];
    int i,k,j;
    char n;
    int count=0;
    Stack thestack;
    FindInDegree(G,indegree);//对各顶点求入度indegree[0....num]
    InitStack(thestack);//初始化栈
    for(i=0;i<G.num;i++)
    Console.WriteLine("结点"+G.vertices[i].data+"的入度为"+indegree[i]);
    for(i=0;i<G.num;i++)
    {
    if(indegree[i]==0)
    Push(thestack.vertices[i]);
    }
    Console.Write("拓扑排序输出顺序为:");
    while(thestack.Peek()!=null)
    {
    Pop(thestack.Peek());
    j=locatevex(G,n);
    if (j==-2)
    {
    Console.WriteLine("发生错误,程序结束。");
    exit();
    }
    Console.Write(G.vertices[j].data);
    count++;
    for(p=G.vertices[j].firstarc;p!=NULL;p=p.nextarc)
    {
    k=p.adjvex;
    if (!(--indegree[k]))
    Push(G.vertices[k]);
    }
    }
    if (count<G.num)
    Cosole.WriteLine("该图有环,出现错误,无法排序。");
    else
    Console.WriteLine("排序成功。");
    }
    ----------------------------------------Code--------------------------------------
    算法的时间复杂度O(n+e)。
    九、锦标赛排序
    锦标赛排序的算法**与体育比赛类似。
    首先将n个数据元素两两分组,分别按关键字进行比较,得到n/2个比较的优胜者(关键字小者),作为第一步比较的结果保留下来,
    然后对这n/2个数据元素再两两分组,分别按关键字进行比较,…,如此重复,直到选出一个关键字最小的数据元素为止。
    --------------------------------Code in C---------------------------------------

    include <stdio.h>

    include <stdlib.h>

    include <string.h>

    include <math.h>

    define SIZE 100000

    define MAX 1000000

    struct node
    {
    long num;//关键字
    char str[10];
    int lastwin;//最后胜的对手
    int killer;//被击败的对手
    long times;//比赛次数
    }data[SIZE];
    long CompareNum=0;
    long ExchangeNum=0;
    long Read(char name[])//读取文件a.txt中的数据,并存放在数组data[]中;最后返回数据的个数
    {
    FILE *fp;
    long i=1;
    fp=fopen(name,"rw");
    fscanf(fp,"%d%s",&data[i].num,data[i].str);
    while(!feof(fp))
    {
    i++;
    fscanf(fp,"%d%s",&data[i].num,data[i].str);
    }
    return (i-1);
    }
    long Create(long num)//创建胜者树,返回冠军(最小数)在数组data[]中的下标
    {
    int i,j1,j2,max,time=1;
    long min;//记录当前冠军的下标
    for(i=1;pow(2,i-1)<num;i++)
    ;
    max=pow(2,i-1);//求叶子结点数目
    for(i=1;i<=max;i++)//初始化叶子结点
    {
    data[i].killer=0;
    data[i].lastwin=0;
    data[i].times=0;
    if(i>num)
    data[i].num=MAX;
    }
    for(i=1;i<=max;i+=2)//第一轮比赛
    {
    ++CompareNum;
    if(data[i].num <= data[i+1].num)
    {
    data[i].lastwin = i+1;
    data[i+1].killer=i;
    ++data[i].times;
    ++data[i+1].times;
    min=i;
    }
    else
    {
    data[i+1].lastwin=i;
    data[i].killer=i+1;
    ++data[i].times;
    ++data[i+1].times;
    min=i+1;
    }
    }
    j1=j2=0;//记录连续的两个未被淘汰的选手的下标
    while(time <= (log(max)/log(2)))//进行淘汰赛
    {
    for(i=1;i<=max;i++)
    {
    if(data[i].times==time && data[i].killer==0)//找到一名选手
    {
    j2=i;//默认其为两选手中的后来的
    if(j1==0)//如果第一位置是空的,则刚来的选手先来的
    j1=j2;
    else//否则刚来的选手是后来的,那么选手都已到场比赛开始
    {
    ++CompareNum;
    if(data[j1].num <= data[j2].num)//先来的选手获胜
    {
    data[j1].lastwin = j2;//最后赢的是j2
    data[j2].killer=j1;//j2是被j1淘汰的
    ++data[j1].times;
    ++data[j2].times;//两选手场次均加1
    min=j1;//最小数下标为j1
    j1=j2=0;//将j1,j2置0
    }
    else//同理
    {
    data[j2].lastwin=j1;
    data[j1].killer=j2;
    ++data[j1].times;
    ++data[j2].times;
    min=j2;
    j1=j2=0;
    }
    }
    }
    }
    time++;//轮数加1
    }
    return min;//返回冠军的下标
    }
    void TournamentSort(long num)//锦标赛排序
    {
    long tag=Create(num);//返回最小数下标
    FILE *fp1;
    fp1=fopen("sort.txt","w+");//为写入创建并打开文件sort.txt
    while(data[tag].num != MAX)//当最小值不是无穷大时
    {
    printf("%d %s\n",data[tag].num,data[tag].str);//输出数据
    fprintf(fp1,"%d %s\n",data[tag].num,data[tag].str);//写入数据
    data[tag].num=MAX;//将当前冠军用无穷大替换
    tag=Create(num);//返回下一个冠军的下标
    }
    }
    int main()
    {
    int num;
    char name[10];
    printf("Input name of the file:");
    gets(name);
    num=Read(name);//读文件
    TournamentSort(num);//锦标赛排序
    printf("CompareNum=%d\nExchangeNum=%d\n",CompareNum,ExchangeNum);
    return 0;
    }
    ------------------------------------------Code-------------------------------------
    十、基数排序
    基数排序又被称为桶排序。与前面介绍的几种排序方法相比较,基数排序和它们有明显的不同。
    前面所介绍的排序方法都是建立在对数据元素关键字进行比较的基础上,所以可以称为基于比较的排序;
    而基数排序首先将待排序数据元素依次“分配”到不同的桶里,然后再把各桶中的数据元素“收集”到一起。
    通过使用对多关键字进行排序的这种“分配”和“收集”的方法,基数排序实现了对多关键字进行排序。
    ———————————————————————————————————————
    例:
    每张扑克牌有两个“关键字”:花色和面值。其大小顺序为:
    花色:§<¨<©<ª
    面值:2<3<……<K<A
    扑克牌的大小先根据花色比较,花色大的牌比花色小的牌大;花色一样的牌再根据面值比较大小。所以,将扑克牌按从小到大的次序排列,可得到以下序列:
    §2,…,§A,¨2,…,¨A,©2,…,©A,ª2,…,ªA
    这种排序相当于有两个关键字的排序,一般有两种方法实现。
    其一:可以先按花色分成四堆(每一堆牌具有相同的花色),然后在每一堆牌里再按面值从小到大的次序排序,最后把已排好序的四堆牌按花色从小到大次序叠放在一起就得到排序的结果。
    其二:可以先按面值排序分成十三堆(每一堆牌具有相同的面值),然后将这十三堆牌按面值从小到大的顺序叠放在一起,再把整副牌按顺序根据花色再分成四堆(每一堆牌已按面值从小到大的顺序有序),最后将这四堆牌按花色从小到大合在一起就得到排序的结果。
    ———————————————————————————————————————
    实现方法:
    最高位优先(Most Significant Digit first)法,简称MSD法:先按k1排序分组,同一组中记录,关键码k1相等,再对各组按k2排序分成子组,之后,对后面的关键码继续这样的排序分组,直到按最次位关键码kd对各子组排序后。再将各组连接起来,便得到一个有序序列。
    最低位优先(Least Significant Digit first)法,简称LSD法:先从kd开始排序,再对kd-1进行排序,依次重复,直到对k1排序后便得到一个有序序列。
    ---------------------------------Code in C#------------------------------------------
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace LearnSort
    {
    class Program
    {
    static void Main(string[] args)
    {
    int[] arr = CreateRandomArray(10);//产生随机数组
    Print(arr);//输出数组
    RadixSort(ref arr);//排序
    Print(arr);//输出排序后的结果
    Console.ReadKey();
    }
    public static void RadixSort(ref int[] arr)
    {
    int iMaxLength = GetMaxLength(arr);
    RadixSort(ref arr, iMaxLength);
    }
    private static void RadixSort(ref int[] arr, int iMaxLength)
    {
    List list = new List();//存放每次排序后的元素
    List[] listArr = new List[10];//十个桶
    char currnetChar;//存放当前的字符比如说某个元素123 中的2
    string currentItem;//存放当前的元素比如说某个元素123
    for (int i = 0; i < listArr.Length; i++)//给十个桶分配内存初始化。
    listArr[i] = new List();
    for (int i = 0; i < iMaxLength; i++)//一共执行iMaxLength次,iMaxLength是元素的最大位数。
    {
    foreach (int number in arr)//分桶
    {
    currentItem = number.ToString();//将当前元素转化成字符串
    try { currnetChar = currentItem[currentItem.Length-i-1]; }//从个位向高位开始分桶
    catch { listArr[0].Add(number); continue; }//如果发生异常,则将该数压入listArr[0]。比如说5 是没有十位数的,执行上面的操作肯定会发生越界异常的,这正是期望的行为,我们认为5的十位数是0,所以将它压入listArr[0]的桶里。
    switch (currnetChar)//通过currnetChar的值,确定它压人哪个桶中。
    {
    case '0': listArr[0].Add(number); break;
    case '1': listArr[1].Add(number); break;
    case '2': listArr[2].Add(number); break;
    case '3': listArr[3].Add(number); break;
    case '4': listArr[4].Add(number); break;
    case '5': listArr[5].Add(number); break;
    case '6': listArr[6].Add(number); break;
    case '7': listArr[7].Add(number); break;
    case '8': listArr[8].Add(number); break;
    case '9': listArr[9].Add(number); break;
    default: throw new Exception("unknow error");
    }
    }
    for (int j = 0; j < listArr.Length; j++)//将十个桶里的数据重新排列,压入list
    foreach (int number in listArr[j].ToArray())
    {
    list.Add(number);
    listArr[j].Clear();//清空每个桶
    }
    arr = list.ToArray();//arr指向重新排列的元素
    //Console.Write("{0} times:",i);
    Print(arr);//输出一次排列的结果
    list.Clear();//清空list
    }
    }
    //得到最大元素的位数
    private static int GetMaxLength(int[] arr)
    {
    int iMaxNumber = Int32.MinValue;
    foreach (int i in arr)//遍历得到最大值
    {
    if (i > iMaxNumber)
    iMaxNumber = i;
    }
    return iMaxNumber.ToString().Length;//这样获得最大元素的位数是不是有点投机取巧了...
    }
    //输出数组元素
    public static void Print(int[] arr)
    {
    foreach (int i in arr)
    System.Console.Write(i.ToString()+'\t');
    System.Console.WriteLine();
    }
    //产生随机数组。随机数的范围是0到1000。参数iLength指产生多少个随机数
    public static int[] CreateRandomArray(int iLength)
    {
    int[] arr = new int[iLength];
    Random random = new Random();
    for (int i = 0; i < iLength; i++)
    arr[i] = random.Next(0,1001);
    return arr;
    }
    }
    }
    ---------------------------------Code ---------------------------------------------
    基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的比较性排序法。

    display:inline,display:inline-block,display:block 区别

    之前一直迷惑于display:inline/inline-block/block的异同,在度娘谷哥的帮助下,突然有了一点思路。

    按照网上的介绍,inline将对象转化为内联元素,block将对象转化为块元素,而inline-block则将对象转化为具有块属性的内联元素。

    可能是因为本人理解能力有限,一直很纠结着难以理解这个说法。后来看到这么一个解释[1]:

    内联元素即所有元素都在一行上,无前后换行符,且无法限定高宽,即高宽为其内容的高宽。例如,,,都是内联元素的例子。

    块元素即总在新行上开始,可控制高宽。

    ,

    ,

    ,

    为块元素的例子。

    从例子上说,对span进行背景色限定时,会发现span的背景色总是和文字大小相符,即说明了内联元素的特性。而对div增加背景色限定,则可无视其内容,根据div的高宽进行渲染。

    但是,如果需要对span进行背景色限定,但又要对span的大小做规定,那就用到了inline-block。

    <style> #content{width:auto;height:200px;} .blockdiv{background:#ccc;width:50%;height:50px;} .inlinespan{background:#f60;width:50%;height:50px;} </style>
    这段文字用于测试div的大小
    这段文字用于测试span的大小

    例如上面这个例子,假如想使div.blockdiv和span.inlinespan在一行,但又希望控制div.blockdiv的高度,即可使用div.blockdiv{display:inline-block;}

    inline-block即将对象对外转换为内联元素,但对内其内容又可限定高宽,具有块元素的特征属性。这样一来,规定了inline-block的元素会和周围inline的元素在一行,但它又可以指定高宽。

    仍旧是万恶的IE,IE6/7对inline-block的支持不够完善。因此需要采用hack的方式,但首先需要明了这种hack的原理:

    这是IE的一个经典bug,如果先定义了display:inline-block,然后再设置display回inline或block,layout不会消失。但需要在两个css中[2]。
    

    IE6/7可识别的hack为*,IE6为_。参考[3,4]后,认定在现在IE6/7下的inline-block可通过以下原理实现。在IE中的方式有以下几种,例如object

    1、#object{

      display:inline-block;//激活inline-block,使之在除IE8/7/6下的浏览器均实现,同时使IE下元素触发block

      zoom:1;//激活IE下的对象haslayout属性

    }

      #object{

      *display:inline;//IE6/7下的对象在保持有haslayout属性前提下,表现为inline

    }

    2、#object{

       float:left;//触发layout,表现为块元素

       display:inline;//使之产生inline效果

    }

    3、#object{

      display:inline; //先使对象呈内联状态

      zoom:1; //激活layout

    }

    因此,display:inline-block在IE中的hack可表现为:

    1、为对象增加haslayout属性,使之表现为块元素

    2、将对象转换为inline.(haslayout不消失)

    3、顺序可颠倒。

    参考:

    1.http://www.cnblogs.com/jdonson/archive/2011/06/10/2077932.html

    2.http://ideal.ncepu.me/2012/03/25/1-182/

    3.http://www.68design.net/Web-Guide/HTMLCSS/41207-4.html

    4.http://www.codesky.net/article/201107/169482.html

    利用js加载本地图片预览功能

    直接上代码:

    经测试,除safari6包括6以下不支持,其他均可正常显示。

    原因:safari6不支持filereader,同时不能使用IE滤镜导致失效。

    fix: 可以利用canvas,解决safari6的问题

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    
    
    <head>    
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
    <title>图片上传本地预览</title>    
    <style type="text/css">
    #preview{width:260px;height:190px;border:1px solid #000;overflow:hidden;}
    #imghead {filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=image);}
    </style>
    <script type="text/javascript">
    
            //图片上传预览    IE是用了滤镜。
            function previewImage(file)
            {
              var MAXWIDTH  = 260;
              var MAXHEIGHT = 180;
              var div = document.getElementById('preview');
              if (file.files && file.files[0])
              {
                  div.innerHTML ='<img id=imghead>';
                  var img = document.getElementById('imghead');
                  img.onload = function(){
                    var rect = clacImgZoomParam(MAXWIDTH, MAXHEIGHT, img.offsetWidth, img.offsetHeight);
                    img.width  =  rect.width;
                    img.height =  rect.height;
    //                 img.style.marginLeft = rect.left+'px';
                    img.style.marginTop = rect.top+'px';
                  }
                  var reader = new FileReader();
                  reader.onload = function(evt){img.src = evt.target.result;}
                  reader.readAsDataURL(file.files[0]);
              }
              else //兼容IE
              {
                var sFilter='filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src="';
                file.select();
                var src = document.selection.createRange().text;
                div.innerHTML = '<img id=imghead>';
                var img = document.getElementById('imghead');
                img.filters.item('DXImageTransform.Microsoft.AlphaImageLoader').src = src;
                var rect = clacImgZoomParam(MAXWIDTH, MAXHEIGHT, img.offsetWidth, img.offsetHeight);
                status =('rect:'+rect.top+','+rect.left+','+rect.width+','+rect.height);
                div.innerHTML = "<div id=divhead style='width:"+rect.width+"px;height:"+rect.height+"px;margin-top:"+rect.top+"px;"+sFilter+src+"\"'></div>";
              }
            }
            function clacImgZoomParam( maxWidth, maxHeight, width, height ){
                var param = {top:0, left:0, width:width, height:height};
                if( width>maxWidth || height>maxHeight )
                {
                    rateWidth = width / maxWidth;
                    rateHeight = height / maxHeight;
    
                    if( rateWidth > rateHeight )
                    {
                        param.width =  maxWidth;
                        param.height = Math.round(height / rateWidth);
                    }else
                    {
                        param.width = Math.round(width / rateHeight);
                        param.height = maxHeight;
                    }
                }
    
                param.left = Math.round((maxWidth - param.width) / 2);
                param.top = Math.round((maxHeight - param.height) / 2);
                return param;
            }
    </script>    
    </head>    
    <body>
    <div id="preview">
        <img id="imghead" width=100 height=100 border=0 src=''>
    </div>
    
    
        <input type="file" onchange="previewImage(this)" />    
    </body>    
    </html>
    

    史上最全的CSS hack方式

    做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况。基于此,某些情况我们会极不情愿的使用这个不太友好的方式来达到大家要求的页面表现。我个人是不太推荐使用hack的,要知道一名好的前端,要尽可能不使用hack的情况下实现需求,做到较好的用户体验。可是啊,现实太残酷,浏览器厂商之间历史遗留的问题让我们在目标需求下不得不向hack妥协,虽然这只是个别情况。今天,结合自己的经验和理解,做了几个demo把IE6~IE10和其他标准浏览器的CSS hack做一个总结,也许本文应该是目前最全面的hack总结了吧。

    什么是CSS hack
    由于不同厂商的流览器或某浏览器的不同版本(如IE6-IE11,Firefox/Safari/Opera/Chrome等),对CSS的支持、解析不一样,导致在不同浏览器的环境中呈现出不一致的页面展现效果。这时,我们为了获得统一的页面效果,就需要针对不同的浏览器或不同版本写特定的CSS样式,我们把这个针对不同的浏览器/不同版本写相应的CSS code的过程,叫做CSS hack!

    CSS hack的原理
    由于不同的浏览器和浏览器各版本对CSS的支持及解析结果不一样,以及CSS优先级对浏览器展现效果的影响,我们可以据此针对不同的浏览器情景来应用不同的CSS。

    CSS hack分类
    CSS Hack大致有3种表现形式,CSS属性前缀法、选择器前缀法以及IE条件注释法(即HTML头部引用if IE)Hack,实际项目中CSS Hack大部分是针对IE浏览器不同版本之间的表现差异而引入的。

    属性前缀法(即类内部Hack):例如 IE6能识别下划线""和星号" * ",IE7能识别星号" * ",但不能识别下划线"",IE6~IE10都认识"\9",但firefox前述三个都不能认识。
    选择器前缀法(即选择器Hack):例如 IE6能识别_html .class{},IE7能识别_+html .class{}或者*:first-child+html .class{}。
    IE条件注释法(即HTML条件注释Hack):针对所有IE(注:IE10+已经不再支持条件注释): ,针对IE6及以下版本: 。这类Hack不仅对CSS生效,对写在判断语句里面的所有代码都会生效。
      
    CSS hack书写顺序,一般是将适用范围广、被识别能力强的CSS定义在前面。

    CSS hack方式一:条件注释法
     
    这种方式是IE浏览器专有的Hack方式,微软官方推荐使用的hack方式。举例如下

    只在IE下生效
    <!--[if IE]>
    这段文字只在IE浏览器显示
    <![endif]-->
    
    只在IE6下生效
    <!--[if IE 6]>
    这段文字只在IE6浏览器显示
    <![endif]-->
    
    只在IE6以上版本生效
    <!--[if gte IE 6]>
    这段文字只在IE6以上(包括)版本IE浏览器显示
    <![endif]-->
    
    只在IE8上不生效
    <!--[if ! IE 8]>
    这段文字在非IE8浏览器显示
    <![endif]-->
    
    非IE浏览器生效
    <!--[if !IE]>
    这段文字只在非IE浏览器显示
    <![endif]-->
    

    CSS hack方式二:类内属性前缀法
    属性前缀法是在CSS样式属性名前加上一些只有特定浏览器才能识别的hack前缀,以达到预期的页面展现效果。

    IE浏览器各版本 CSS hack 对照表

    hack 写法 实例 IE6(S) IE6(Q) IE7(S) IE7(Q) IE8(S) IE8(Q) IE9(S) IE9(Q) IE10(S) IE10(Q)

    • *color 青色 Y Y Y Y N Y N Y N Y
    • +color 绿色 Y Y Y Y N Y N Y N Y
    • -color 黄色 Y Y N N N N N N N N
      _ _color 蓝色 Y Y N Y N Y N Y N N

    #color 紫色 Y Y Y Y N Y N Y N Y

    \0 color:red\0 红色 N N N N Y N Y N Y N
    \9\0 color:red\9\0 粉色 N N N N N N Y N Y N
    !important color:blue !important;color:green; 棕色 N N Y N Y N Y N Y Y
    说明:在标准模式中

    “-″减号是IE6专有的hack
    “\9″ IE6/IE7/IE8/IE9/IE10都生效
    “\0″ IE8/IE9/IE10都生效,是IE8/9/10的hack
    “\9\0″ 只对IE9/IE10生效,是IE9/10的hack
    demo如下

    [css] view plaincopy

    <script type="text/javascript"> //alert(document.compatMode); </script> <style type="text/css"> body:nth-of-type(1) .iehack{ color: #F00;/* 对Windows IE9/Firefox 7+/Opera 10+/所有Chrome/Safari的CSS hack ,选择器也适用几乎全部Mobile/Linux/Mac browser*/ } .demo1,.demo2,.demo3,.demo4{ width:100px; height:100px; } .hack{ /*demo1 */ /*demo1 注意顺序,否则IE6/7下可能无法正确显示,导致结果显示为白色背景*/ background-color:red; /* All browsers */ background-color:blue !important;/* All browsers but IE6 */ *background-color:black; /* IE6, IE7 */ +background-color:yellow;/* IE6, IE7*/ background-color:gray\9; /* IE6, IE7, IE8, IE9, IE10 */ background-color:purple\0; /* IE8, IE9, IE10 */ background-color:orange\9\0;/*IE9, IE10*/ _background-color:green; /* Only works in IE6 */ *+background-color:pink; /* WARNING: Only works in IE7 ? Is it right? */ } /*可以通过javascript检测IE10,然后给IE10的标签加上class=”ie10″ 这个类 */ .ie10 #hack{ color:red; /* Only works in IE10 */ } /*demo2*/ .iehack{ /*该demo实例是用于区分标准模式下ie6~ie9和Firefox/Chrome的hack,注意顺序 IE6显示为:绿色, IE7显示为:黑色, IE8显示为:红色, IE9显示为:蓝色, Firefox/Chrome显示为:橘色, (本例IE10效果同IE9,Opera最新版效果同IE8) */ background-color:orange; /* all - for Firefox/Chrome */ background-color:red\0; /* ie 8/9/10/Opera - for ie8/ie10/Opera */ background-color:blue\9\0; /* ie 9/10 - for ie9/10 */ *background-color:black; /* ie 6/7 - for ie7 */ _background-color:green; /* ie 6 - for ie6 */ } /*demo3 实例是用于区分标准模式下ie6~ie9和Firefox/Chrome的hack,注意顺序 IE6显示为:红色, IE7显示为:蓝色, IE8显示为:绿色, IE9显示为:粉色, Firefox/Chrome显示为:橘色, (本例IE10效果同IE9,Opera最新版效果也同IE9为粉色) */ .element { background-color:orange; /* all IE/FF/CH/OP*/ } .element { *background-color: blue; /* IE6+7, doesn't work in IE8/9 as IE7 */ } .element { _background-color: red; /* IE6 */ } .element { background-color: green\0; /* IE8+9+10 */ } :root .element { background-color:pink\0; } /* IE9+10 */ /*demo4*/ /* 该实例是用于区分标准模式下ie6~ie10和Opera/Firefox/Chrome的hack,本例特别要注意顺序 IE6显示为:橘色, IE7显示为:粉色, IE8显示为:黄色, IE9显示为:紫色, IE10显示为:绿色, Firefox显示为:蓝色, Opera显示为:黑色, Safari/Chrome显示为:灰色, */ .hacktest{ background-color:blue; /* 都识别,此处针对firefox */ background-color:red\9; /*all ie*/ background-color:yellow\0; /*for IE8/IE9/10 最新版opera也认识*/ +background-color:pink; /*for ie6/7*/ _background-color:orange; /*for ie6*/ } @media screen and (min-width:0){ .hacktest {background-color:black\0;} /*opera*/ } @media screen and (min-width:0) { .hacktest { background-color:purple\9; }/* for IE9/IE10 PS:国外有些习惯常写作\0,根本没考虑Opera也认识\0的实际 */ } @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { .hacktest { background-color:green; } /* for IE10+ 此写法可以适配到高对比度和默认模式,故可覆盖所有ie10的模式 */ } @media screen and (-webkit-min-device-pixel-ratio:0){ .hacktest {background-color:gray;} } /*for Chrome/Safari*/ /* #963棕色 :root is for IE9/IE10, 优先级高于@media, 慎用!如果二者合用,必要时在@media样式加入 !important 才能区分IE9和IE10 */ /* :root .hacktest { background-color:#963\9; } */ </style>

    demo1是测试不同IE浏览器下hack 的显示效果
    IE6显示为:粉色,
    IE7显示为:粉色,
    IE8显示为:蓝色,
    IE9显示为:蓝色,
    Firefox/Chrome/Opera显示为:蓝色,
    若去掉其中的!important属性定义,则IE6/7仍然是粉色,IE8是紫色,IE9/10为橙色,Firefox/Chrome变为红色,Opera是紫色。是不是有些奇怪:除了IE6以外,其他所有的表现都符合我们的期待。那为何IE6表现的颜色不是_background-color:green;的绿色而是_+background-color:pink的粉色呢?其实是最后一句所谓的IE7私有hack惹的祸?不是说_+是IE7的专有hack吗???错,你可能太粗心了!我们常说的IE7专有_+hack的格式是_+html selector,而不是上面的直接在属性上加*+前缀。如果是为IE7定制特殊样式,应该这样使用:

    +html #ie7test { / IE7 only_/
    color:green;
    }
    经过测试,我发现属性前缀_+background-color:pink;只有IE6和IE7认识。而*+html selector只有IE7认识。所以我们在使用时候一定要特别注意。

    demo2实例是用于区分标准模式下ie6~ie9和Firefox/Chrome的hack,注意顺序
    IE6显示为:绿色,
    IE7显示为:黑色,
    IE8显示为:红色,
    IE9显示为:蓝色,
    Firefox/Chrome显示为:橘色,
    (本例IE10效果同IE9,Opera最新版效果同IE8)

    demo3实例也是用于区分标准模式下ie6~ie9和Firefox/Chrome的hack,注意顺序
    IE6显示为:红色,
    IE7显示为:蓝色,
    IE8显示为:绿色,
    IE9显示为:粉色,
    Firefox/Chrome显示为:橘色,
    (本例IE10效果同IE9,Opera最新版效果也同IE9为粉色)

    demo4实例是用于区分标准模式下ie6~ie10和Opera/Firefox/Chrome的hack,本例特别要注意顺序
    IE6显示为:橘色,
    IE7显示为:粉色,
    IE8显示为:黄色,
    IE9显示为:紫色,
    IE10显示为:绿色,
    Firefox显示为:蓝色,
    Opera显示为:黑色,
    Safari/Chrome显示为:灰色,

    CSS hack方式三:选择器前缀法
    选择器前缀法是针对一些页面表现不一致或者需要特殊对待的浏览器,在CSS选择器前加上一些只有某些特定浏览器才能识别的前缀进行hack。

    目前最常见的是

    *html *前缀只对IE6生效
    *+html *+前缀只对IE7生效
    @media screen\9{...}只对IE6/7生效
    @media \0screen {body { background: red; }}只对IE8有效
    @media \0screen,screen\9{body { background: blue; }}只对IE6/7/8有效
    @media screen\0 {body { background: green; }} 只对IE8/9/10有效
    @media screen and (min-width:0\0) {body { background: gray; }} 只对IE9/10有效
    @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {body { background: orange; }} 只对IE10有效
    等等
    结合CSS3的一些选择器,如html:first-child,body:nth-of-type(1),衍生出更多的hack方式,具体的可以参考下表:

    CSS3选择器结合JavaScript的Hack
    我们用IE10进行举例:

    由于IE10用户代理字符串(UserAgent)为:Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0),所以我们可以使用javascript将此属性添加到文档标签中,再运用CSS3基本选择器匹配。

    JavaScript代码:

    var htmlObj = document.documentElement;
    htmlObj.setAttribute('data-useragent',navigator.userAgent);
    htmlObj.setAttribute('data-platform', navigator.platform );
    

    CSS3匹配代码:

    html[data-useragent*='MSIE 10.0'] #id {
    color: #F00;
    }
    CSS hack利弊
    一般情况下,我们尽量避免使用CSS hack,但是有些情况为了顾及用户体验实现向下兼容,不得已才使用hack。比如由于IE8及以下版本不支持CSS3,而我们的项目页面使用了大量CSS3新属性在IE9/Firefox/Chrome下正常渲染,这种情况下如果不使用css3pie或htc或条件注释等方法时,可能就得让IE8-的专属hack出马了。使用hack虽然对页面表现的一致性有好处,但过多的滥用会造成html文档混乱不堪,增加管理和维护的负担。相信只要大家一起努力,少用、慎用hack,未来一定会促使浏览器厂商的标准越来越趋于统一,顺利过渡到标准浏览器的主流时代。抛弃那些陈旧的IE hack,必将减轻我们编码的复杂度,少做无用功。

    最后补上一张引自国外某大牛总结的CSS hack表,这时一张6年前的旧知识汇总表了,放在这里仅供需要时候方便参考。

    说明:本文测试环境为IE6~IE10,Chrome 29.0.1547.66 m,Firefox 20.0.1 ,Opera 12.02等。一边工作,一边总结,总结了几天写下整理好,今天把它分享出来,文中难免有纰漏,如大侠发现请及时告知!

    转载请注明来自CSDN freshlover的博客专栏《史上最全CSS Hack方式一览》

    手机端MVC-js框架-Gillie-中文版本

    译者声明:

      1、代码库发布在http://pablovallejo.github.io/gillie/

      2、查看API介绍直接戳这里看整理。

    Gillie是一个轻型MVC框架,受Backbone的启发实现。它提供了一些方法,可以实现RESTful HTTP请求,同时允许使用models,views和handlers来分离功能点。另外提供了事件API,从而views可以监听模型事件并采取适当行为,最终以这种方式实现了监听者设计模式。

    获取代码

    开发者版本 16 k

    应用版本 4 K

    CDN版本:

      <script src="//cdnjs.cloudflare.com/ajax/libs/gillie/0.2.1/gillie.min.js"></script>

    历史沿革:

    作者曾在某具有大型代码库的javascript项目中工作,在了解backbone之后决定创建这个小型库来实现backbone的一些特性及其架构。最终我们将足够的功能添加到这个库里。

    译者:这个库提供了Mvvm框架下的基本功能,同时因其体积和灵活性,可以很好的适配到手机端

    构建app

    Gillie 遵循MVC设计,其中控制器(controller)称为处理器(handler)。处理器是用于监听DOM事件,获取数据,并且将数据传递给模型存储。一旦模型完成了存储数据的行为,将触发一个事件,通常是与监听模型的视图(view)有关,从而重绘DOM

    小知识:repaint / reflow

    理念:

    Gillie目的是使开发者更简单的使用javascript开发模式,理解基本的MV*(MVVM,MVC)模型,从而更易于使用其他类似于backbone,angularJS,emberJS之类的框架。

    小知识: MVVM : 英文原版 (中文翻译)

    示例一:hello world!

    定义处理器:

    复制代码
    var MainHandler = Gillie.Handler.extend({

    initialize: function() {
        alert( 'Hello world!' );
    }
    

    });

    //创建handler实例
    var mainHandler = new MainHandler();
    复制代码
    定义dom处理器:

    复制代码
    var AppHandler = Gillie.Handler.extend({

        events: {
            'click a': 'turnRed'
        }
    
    ,   turnRed: function( e ) {
            e.preventDefault();
    
            var target = e.currentTarget;
            $( target ).css( 'color', 'red' );
    
        }
    

    });

    // 创建处理器实例
    var appHandler = new AppHandler();
    复制代码

    示例二:todo 应用(在服务器保存数据)

    模型(model)定义

    当post请求完成后,将会触发模型中的事件,将实例和服务器响应返回给监听者

    复制代码
    var TodoModel = Gillie.Model.extend({

        url: 'http://localhost/api/'
    
    ,   create: function( event ) {
            this.Post( 'todo/', event );
        }
    

    });

    // 创建模型实例
    var todoModel = new TodoModel();
    复制代码
    视图(View)定义

    复制代码
    var TodoView = Gillie.View.extend({

        initialize: function() {
    
            // 绑定’todo.create’事件
            todoModel.on( 'todo.create', this.onCreate );
        }
    
    
    ,   onCreate: function( instance, response ) {
            alert( instance.get( 'title' ) + '. Has been saved' );
        }
    

    });

    // 创建视图实例
    var todoView = new TodoView();
    复制代码
    处理器(Handler)定义

    复制代码
    var TodoHandler = Gillie.Handler.extend({

        events: {
            'keypress #new-todo': 'createOnEnter'
        }
    
    ,   createOnEnter: function( e ) {
    
            var enterKey = 13
            ,   currentTarget = e.currentTarget;
    
            if ( e.which != enterKey ) return;
    
            var title = $( target ).val();
            todoModel.set( 'title', title )
                .create( 'todo.create' );
    
        }
    

    });

    // 创建处理器实例
    var todoHandler = new TodoHandler();
    复制代码
    使用方式

    包含脚本时,模型定义在先,视图和处理器定义在后。这样视图和处理器可以使用模型。

    <script src="js/jquery.js"></script> <script src="js/gillie.js"></script> <script src="js/yourapp.js"></script>

    正确示例:

    <script src="js/models/post.js"></script> <script src="js/views/post.js"></script>

    <!— 模型定义在先,从而处理器可以创建模型 -->

    <script src="js/handler/post.js"></script>

    错误示例:

    复制代码
    <!— 处理器定义无法访问post模型 -->

    <script src="js/handler/post.js"></script>

    <!— 由于未定义模型,使得视图无法监听post模型-->

    <script src="js/views/post.js"></script>

    <!— 虽然在视图及处理器之后加入模型,但前者已经无法访问模型了-->

    <script src="js/models/post.js"></script>

    复制代码

    处理器(Handler)API参考

    Handlers属于应用程序,关注DOM事件监听,例如点击,提交表单,按键弹起,以及类似的动作,进而获取到他们的数据,传递给模型来存储到数据库中,并通知视图改动事件。

    initialize: function()

    复制代码
    //初始化API:初始化处理器,在模型和视图中有类似的方法,每次实例创建时均被调用
    //使用方法:
    var Posts = Gillie.Handler.extend({

    initialize: function() {
    
        // 从所有的posts中获取信息并触发’posts.get’事件
    // 监听者获知事件,从而重新渲染
        model.sync( 'posts.get' );
    }
    

    });
    // Posts 实例
    var posts = new Post();
    复制代码
    Element el: string

    复制代码
    //el属性值为定义事件的容器,当指定该值到.post-box时,所有在事件属性中定义的事件,都将仅绑定到.post-box的内部元素
    //如果el没有指定,事件将绑定到document上
    //使用方法
    var Posts = Gillie.Handler.extend({

        // 绑定容器
        el: '.posts-container'
    
    ,   events: {
            'click .post-title': 'showPost'
        }
    
        // Show post 方法
    ,   showPost: function( e ) {
            e.preventDefault();
    
            //做点什么吧...
        }
    

    });

    // 创建实例,启动监听
    var posts = new Posts();
    复制代码
    Events events: {}

    复制代码
    //Events值为对象类型,用于绑定dom事件,并且将其部署到处理器回调方法中
    //在回调中,上下文环境为处理器自身。也就是说,处理器中定义的方法可以在处理器其他方法的事件回调中调用。
    //使用方法
    var Posts = Gillie.Handler.extend({

        events: {
                'click .post-title': 'showPost'
            ,   'submit .update-post': 'updatePost'
            ,   'keyup .posts-search-field': 'findPosts'
        }
    
    ,   showPost: function( e ) {
    
            // 例如此处,可以调用该处理器的其他成员方法
            var title = this.cleanTitle(
                $( e.currentTarget ).data( 'title' );
            );
    
            //做点什么吧...
        }
    
    ,   cleanTitle: function( title ) {
            //做点什么吧...
        }
    
    ,   updatePost: function( e ) {
            //做点什么吧...
        }
    
    ,   searchPosts: function( e ) {
            //做点什么吧...
        }
    

    });

    // 创建视图实例
    var posts = new Posts();
    复制代码
    模型(Model) API 参考
    initialize: function() {}

    参数:无;返回值:无

    复制代码
    //该方法没有参数,也没有返回值,每次视图、模型和处理器被实例化时均会被调用
    //使用方法:
    var Person = Gillie.Model.extend({

    //实例化时执行
    initialize: function() {
        console.log( 'Person model has been instantiated' );
    }
    

    });

    // 创建实例,将输出" Person model has been instantiated "
    var john = new Person();
    复制代码
    defaults: {}

    复制代码
    //实例化时的初始默认属性。若在模型中设定则会覆盖默认值,也可以使用实例化后模型变量的get(),set()方法设置新值。
    //使用方法
    var Person = Gillie.Model.extend({

    // 默认属性
    defaults: {
            'alias': 'none'
        ,   'picture': 'default.jpg'
    }
    

    });

    // 实例化Person
    var john = new Person();
    // 默认情况下,John的picture属性对应default.jpg
    john.get( 'picture' ); // default.jpg

    // 通过一下方式修改John的picture属性
    john.set( 'picture', 'john-pic.jpg' );
    复制代码
    url: {}

    复制代码
    //该属性定义了所有请求方法的基础url 地址
    //使用方法:
    var Person = Gillie.Model.extend({

        defaults: {
            'picture': 'default.jpg'
        }
    
        // 请求的默认URL地址
    ,   url: 'http://localhost/api/v1/'
    
        // 存储
    ,   save: function() {
    
            this.Post( 'person/', 'person.create' );
        }
    

    });

    var john = new Person({
    'name': 'John'
    , 'picture': 'john.jpg'
    });

    // 模型存储将会发送POST请求到'http://localhost/api/v1/person/'
    john.save();
    复制代码
    http请求方法,提供get .post ,put ,delete方法

    model.Post( path, event, options )

    Post model的post方法,参数为path,event,options,返回值XHR

    参数

    类型

    详细说明

    path

    string

    URL中除去base url的其他部分

    event

    string

    当请求完成后,由model触发的事件

    options

    object

    附加属性,作为ajax返回的其他参数传递,例如success,error等

    复制代码
    //Post model的post方法,参数为path,event,options
    //使用基础URL(base URL)组合path属性成一个完整URL,然后发送post请求。当请求完成后,触发带有这个key值的event事件。因此如果传递了resource.event作为event事件,将会由模型触发,同时监听者将获取到模型实例,并可将服务器响应的值作为参数传递过去。
    //使用方法:
    var Person = Gillie.Model.extend({

    // 创建person
    create: function( event ) {
        this.Post( 'person/', event, {} );
    }
    

    });

    var david = new Person({
    'location': 'Nevada'
    , 'picture': 'david.jpg'
    });

    // 创建person,成功后触发’person.create’事件,从而视图可获知该事件然后基于新的模型数据渲染
    david.create( 'person.create' );
    复制代码

    model.Get( path, event, options )

    复制代码
    //参数及返回值同Post
    //使用方法
    var Person = Gillie.Model.extend({

    // 从服务器端获取数据
    sync: function( event ) {
        this.Get( 'person/:_id', event );
    }
    

    });

    // 创建person对象,并获取其信息
    var maria = new Person({
    _id: 10
    });

    // 获取maria的信息,请求完成后触发’person.get’事件
    maria.get( 'person.get' );
    复制代码
    model.Put( path, event, options )

    复制代码
    //参数及返回值同post
    //使用方法
    var Person = Gillie.Model.extend({

    // 更新person
    update: function( event ) {
        this.Put( 'person/:_id', event );
    }
    

    });

    var jordan = new Person({
    '_id': 11
    , 'localtion': 'New York'
    });

    // 更新Jordan的数据,请求完成后触发’person.update’事件
    jordan.update( 'person.update' );
    复制代码
    model.Delete( path, event, options )

    复制代码
    //参数及返回值同Post
    //使用方法
    var Person = Gillie.Model.extend({

    // 删除person
    delete: function( event ) {
    this.Delete( 'person/:_id', event );
    }

    });

    var jenny = new Person({
    _id: 13
    })

    // 删除服务器上的person信息,完成后触发’person.delete’事件,监听者可据此改变dom以及类似的行为
    jenny.delete( 'person.delete' );
    复制代码
    get、set、unset

    用于获取、设置和移除model属性

    model.get( key ),返回值类型自定

    参数

    类型

    详细说明

    key

    string

    Model的属性

    复制代码
    //获取model的某个属性
    //使用方法
    var Car = Gillie.Model.extend({});

    // 创建一个新的car对象
    var camaro = new Car({
    year: 2014
    , cubic_inches: 378
    , manufacturer: 'Chevrolet'
    });

    // 获取并打印car 对象的 manufacturer属性
    var manufacturer = camaro.get( 'manufacturer' );
    console.log( manufacturer ); // Chevrolet
    复制代码

    model.set( key, val ), model.set( object ),返回值:Objectmodel实例

    参数

    类型

    详细说明

    key

    stringOrobject

    Name of the attribute we're setting. If we pass an object of key value pairs, there is no need to use the second parameter.

    要设置的属性名。如果传递的是key-value对的对象,即不需要第二个参数

    value

    mixed

    要存储的属性值(当第一个参数为对象时,不需要该参数)

    options

    object

    作为ajax返回值传递,例如success,error等

    复制代码
    //设置模型的某个属性或一组属性
    //使用方法
    var Car = Gillie.Model.extend({});

    var camaro = new Car();

    // 传递key-value值对
    camaro.set( 'year', 2014 );

    // 传递多个key-value组成的对象
    camaro.set({
    manufacturer: 'Chevrolet'
    , cubic_inches: 378
    });

    // 获取属性值
    console.log( camaro.get( 'year' ) ); // 2014
    复制代码
    unset model.unset( key )

    复制代码
    //移除模型属性
    //使用方法
    var Car = Gillie.Model.extend({});

    var camaro = new Car({
    year: 2014
    , cubic_inches: 378
    , color: 'black'
    });

    // 移除car对象的color属性
    camaro.unset( 'color' );

    console.log( camaro.get( 'color' ) ); // null
    复制代码
    model.toJSON(),返回值json对象

    复制代码
    //以json对象格式返回模型中定义的属性
    //使用方法
    var Car = Gillie.Model.extend({});

    var camaro = new Car({
    year: 2014
    , manufacturer: 'Chevrolet'
    });

    // 模型属性组合成对象
    var attributes = camaro.toJSON();
    console.log( attributes ); // { year: 2014, manufacturer: 'Chevrolet' }
    复制代码
    events:

    同view和model中的使用方法,用于触发和监听事件

    视图API参考
    gillie基于监听者设计模式,视图尝试监听模型事件,并在DOM上采取动作

    initialize: function()

    复制代码
    //初始化:创建视图实例时调用该初始化方法,用于声明该视图将监听哪些事件
    //使用方法
    var Post = Gillie.View.extend({

        initialize: function() {
    
            // 监听模型’post.create’事件
            model.on( 'post.create', this.onCreate );
        }
    
    
        // post请求完成后调用
    ,   onCreate: function( modelInstance, response ) {
    
            // 渲染dom
        }
    

    });

    // 创建post实例,同时运行初始化方法
    var postView = new Post();
    复制代码
    事件API参考

    事件API提供了三种方法用于触发在view和Model中的事件。

    on( event, fn ),返回当前实例,

    参数

    类型

    详细说明

    event

    string orobject

    绑定的事件。或者包含键值对的对象,即事件名称和对应回掉

    fn, callback

    function

    事件触发时的回掉方法

    复制代码
    //On()方法,用于监听事件,和触发回掉。
    //使用方法
    // 模型定义
    var PostModel = Gillie.Model.extend({

        url: 'http://localhost/api/v1/'
    
    ,   create: function() {
            this.Post( 'post/', 'post.create' );
        }
    

    });

    // 创建模型实例
    postModel = new PostModel({
    title: 'New post title'
    , description: 'Lorem ipsum dolor sit amet'
    });

    // 视图定义
    var PostsView = Gillie.View.extend({

        initialize: function() {
    
            // 监听模型的’post.create’事件
            postModel.on( 'posts.create', this.onCreate );
        }
    
        // 当’posts.create’事件触发后回调用该方法
    ,   this.onCreate: function( postInstance ) {
    
            console.log( postInstance.get( 'title' ) +
                '. Has been created.'
            );
        }
    

    });
    postView = new PostView();

    // 使用模型方法’create’来存储post请求。
    //当post执行完成后,视图将会影响该事件,即打印‘New post title. Has been created’.
    postModel.create();
    复制代码
    trigger( event, data )

    触发事件,同时传递一些特定的值给监听者,返回值当前实例

    参数

    类型

    详细说明

    event

    string

    触发的事件

    data

    mixed

    传递给监听者的数据,可以是一个或多个参数

    复制代码
    //使用方法
    // 创建模型定义和模型实例
    var PostModel = Gillie.Model.extend({});
    var postModel = new PostModel();

    // 视图定义
    var PostView = Gillie.View.extend({

        initialize: function() {
            postModel.on( 'post.custom_event', this.onCustomEvent );
        }
    
    ,   onCustomEvent: function( str, obj ) {
    
            console.log( str ); // 附加数据
            console.log( obj ); // { one: 1, two: 2 }
        }
    

    });

    // 创建视图实例
    var postView = new PostView();

    postModel.trigger(
    'post.custom_event'
    , 'Additional data'
    , { one: 1, two: 2 }
    );
    复制代码
    object.listenTo( object, event, fn )

    设置某个对象监听其他对象的事件,并且事件触发时调用回掉

    参数

    类型

    详细说明

    object

    object

    监听事件的对象

    event

    string

    监听的事件名

    fn

    function

    事件触发时的回掉

    复制代码
    //使用方法
    var PostModel = Gillie.Model.extend({});
    var postModel = new PostModel();

    // 视图定义
    var PostView = Gillie.View.extend({

    onEdit: function( attributes ) {
        console.log( attributes ); // { title: 'New title' }
    }
    

    });
    var postView = new PostView();

    // 监听模型’post.change’事件
    postView.listenTo( postModel, 'post.change', postView.onEdit );

    // 触发模型事件
    postModel.set( 'title', 'New title' )
    .trigger( 'post.change', postModel.toJSON() )
    复制代码
    整理如下:

    Handler
    属性定义 类型 说明 备注 参数 返回值
    initialize function() 初始化处理器,在模型和视图中有类似的方法,每次实例创建时均被调用 每次视图、模型和处理器被实例化时均会调用对应的部分 无 无
    el string 定义事件的容器,当指定该值到.post-box时,所有在事件属性中定义的事件,都将仅绑定到.post-box的内部元素 如果el没有指定,事件将绑定到document上    
    events {} 对象类型,用于绑定dom事件,并且将其部署到处理器回调方法中 在回调中,上下文环境为处理器自身。也就是说,处理器中定义的方法可以在处理器其他方法的事件回调中调用    
    Model
    initialize function() 初始化处理器,在模型和视图中有类似的方法,每次实例创建时均被调用 每次视图、模型和处理器被实例化时均会调用对应的部分 无 无
    defaults {} 实例化时的初始默认属性。若在模型中设定则会覆盖默认值,也可以使用实例化后模型变量的get(),set()方法设置新值。      
    url string 该属性定义了所有请求方法的基础url 地址      
    View
    initialize function() 创建视图实例时调用该初始化方法,用于声明该视图将监听哪些事件 每次视图、模型和处理器被实例化时均会调用对应的部分 无 无
    EVENT API
    on( event, fn )   用于监听事件,和触发回掉。   event:string/object 当前实例
            fn, callback:function  
    trigger( event, data )   触发事件,同时传递一些特定的值给监听者   event:string 当前实例
            data:mixed  
    listenTo( object, event, fn )   设置某个对象监听其他对象的事件,并且事件触发时调用回掉   object object 监听事件的对象  
            event string 监听的事件名  
            fn function 事件触发时的回掉  
    Model API
    model.Post( path, event, options )   使用基础URL(base URL)组合path属性成一个完整URL,然后发送post请求。当请求完成后,触发带有这个key值的event事件。因此如果传递了resource.event作为event事件,将会由模型触发,同时监听者将获取到模型实例,并可将服务器响应的值作为参数传递过去。   path string URL中除去base url的其他部分 XHR
            event string 当请求完成后,由model触发的事件  
            options object 附加属性,作为ajax返回的其他参数传递,例如success,error等  
    model.Get( path, event, options )       同post 同post
    model.Put( path, event, options )       同post 同post
    model.Delete( path, event, options )       同post 同post
    model.get( key )   获取model的某个属性   key string Model的属性 Mixed(多种格式)
    model.set( key, val ), model.set( object )   设置模型的某个属性或一组属性   key stringOrobject 要设置的属性名。如果传递的是key-value对的对象,即不需要第二个参数 model实例
            value mixed 要存储的属性值(当第一个参数为对象时,不需要该参数)  
            options object 作为ajax返回值传递,例如success,error等  
    model.unset( key )   移除模型属性      
    model.toJSON()   以json对象格式返回模型中定义的属性     JSON对象

    javascript事件列表解说

    事件 浏览器支持 解说
    一般事件 onclick IE3、N2 鼠标点击时触发此事件
    ondblclick IE4、N4 鼠标双击时触发此事件
    onmousedown IE4、N4 按下鼠标时触发此事件
    onmouseup IE4、N4 鼠标按下后松开鼠标时触发此事件
    onmouseover IE3、N2 当鼠标移动到某对象范围的上方时触发此事件
    onmousemove IE4、N4 鼠标移动时触发此事件
    onmouseout IE4、N3 当鼠标离开某对象范围时触发此事件
    onkeypress IE4、N4 当键盘上的某个键被按下并且释放时触发此事件.
    onkeydown IE4、N4 当键盘上某个按键被按下时触发此事件
    onkeyup IE4、N4 当键盘上某个按键被按放开时触发此事件
    页面相关事件 onabort IE4、N3 图片在下载时被用户中断
    onbeforeunload IE4、N 当前页面的内容将要被改变时触发此事件
    onerror IE4、N3 出现错误时触发此事件
    onload IE3、N2 页面内容完成时触发此事件
    onmove IE、N4 浏览器的窗口被移动时触发此事件
    onresize IE4、N4 当浏览器的窗口大小被改变时触发此事件
    onscroll IE4、N 浏览器的滚动条位置发生变化时触发此事件
    onstop IE5、N 浏览器的停止按钮被按下时触发此事件或者正在下载的文件被中断
    onunload IE3、N2 当前页面将被改变时触发此事件
    表单相关事件 onblur IE3、N2 当前元素失去焦点时触发此事件
    onchange IE3、N2 当前元素失去焦点并且元素的内容发生改变而触发此事件
    onfocus IE3 、N2 当某个元素获得焦点时触发此事件
    onreset IE4 、N3 当表单中RESET的属性被激发时触发此事件
    onsubmit IE3 、N2 一个表单被递交时触发此事件
    滚动字幕事件 onbounce IE4、N 在Marquee内的内容移动至Marquee显示范围之外时触发此事件
    onfinish IE4、N 当Marquee元素完成需要显示的内容后触发此事件
    onstart IE4、 N 当Marquee元素开始显示内容时触发此事件
    编辑事件 onbeforecopy IE5、N 当页面当前的被选择内容将要复制到浏览者系统的剪贴板前触发此事件
    onbeforecut IE5、 N 当页面中的一部分或者全部的内容将被移离当前页面[剪贴]并移动到浏览者的系统剪贴板时触发此事件
    onbeforeeditfocus IE5、N 当前元素将要进入编辑状态
    onbeforepaste IE5、 N 内容将要从浏览者的系统剪贴板传送[粘贴]到页面中时触发此事件
    onbeforeupdate IE5、 N 当浏览者粘贴系统剪贴板中的内容时通知目标对象
    oncontextmenu IE5、N 当浏览者按下鼠标右键出现菜单时或者通过键盘的按键触发页面菜单时触发的事件
    oncopy IE5、N 当页面当前的被选择内容被复制后触发此事件
    oncut IE5、N 当页面当前的被选择内容被剪切时触发此事件
    ondrag IE5、N 当某个对象被拖动时触发此事件 [活动事件]
    ondragdrop IE、N4 一个外部对象被鼠标拖进当前窗口或者帧
    ondragend IE5、N 当鼠标拖动结束时触发此事件,即鼠标的按钮被释放了
    ondragenter IE5、N 当对象被鼠标拖动的对象进入其容器范围内时触发此事件
    ondragleave IE5、N 当对象被鼠标拖动的对象离开其容器范围内时触发此事件
    ondragover IE5、N 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
    ondragstart IE4、N 当某对象将被拖动时触发此事件
    ondrop IE5、N 在一个拖动过程中,释放鼠标键时触发此事件
    onlosecapture IE5、N 当元素失去鼠标移动所形成的选择焦点时触发此事件
    onpaste IE5、N 当内容被粘贴时触发此事件
    onselect IE4、N 当文本内容被选择时的事件
    onselectstart IE4、N 当文本内容选择将开始发生时触发的事件
    数据绑定 onafterupdate IE4、N 当数据完成由数据源到对象的传送时触发此事件
    oncellchange IE5、N 当数据来源发生变化时
    ondataavailable IE4、N 当数据接收完成时触发事件
    ondatasetchanged IE4、N 数据在数据源发生变化时触发的事件
    ondatasetcomplete IE4、N 当来子数据源的全部有效数据读取完毕时触发此事件
    onerrorupdate IE4、N 当使用onBeforeUpdate事件触发取消了数据传送时,代替onAfterUpdate事件
    onrowenter IE5、N 当前数据源的数据发生变化并且有新的有效数据时触发的事件
    onrowexit IE5、N 当前数据源的数据将要发生变化时触发的事件
    onrowsdelete IE5、N 当前数据记录将被删除时触发此事件
    onrowsinserted IE5、N 当前数据源将要插入新数据记录时触发此事件
    外部事件 onafterprint IE5、N 当文档被打印后触发此事件
    onbeforeprint IE5、N 当文档即将打印时触发此事件
    onfilterchange IE4、N 当某个对象的滤镜效果发生变化时触发的事件
    onhelp IE4、N 当浏览者按下F1或者浏览器的帮助选择时触发此事件
    onpropertychange IE5、N 当对象的属性之一发生变化时触发此事件
    onreadystatechange IE4、N 当对象的初始化属性值发生变化时触发此事件

    网页响应代码列表

    1XX,表示临时响应并需要请求者执行操作以继续

    2XX,表示服务器已成功处理了请求的状态代码

    3XX,要完成请求,还需要进行操作。表示各种转向。

    4XX,表示请求已经出错,妨碍了服务器的处理

    5XX,表示服务器本身可能发生了错误,而不是请求错误。

    以下均来自百度百科。

    状态代码
    状态代码(也称作错误代码),指为服务器所接收每个请求(网页点击)分配的 3 位数代码。多数有效网页点击都有状态代码 200("正常")。"网页未找到"错误会生产 404 错误。某些常见的代码以粗体显示。
    1xx(临时响应)
    用于表示临时响应并需要请求者执行操作才能继续的状态代码。

    代码
    说明
    100(继续)
    请求者应当继续提出请求。服务器返回此代码则意味着,服务器已收到了请求的第一部分,现正在等待接收其余部分。
    101(切换协议)
    请求者已要求服务器切换协议,服务器已确认并准备进行切换。
    2xx(成功)
    用于表示服务器已成功处理了请求的状态代码。
    代码
    说明
    200(成功)
    服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。如果您的 robots.txt 文件显示为此状态,那么,这表示 Googlebot 已成功检索到该文件。
    201(已创建)
    请求成功且服务器已创建了新的资源。
    202(已接受)
    服务器已接受了请求,但尚未对其进行处理。
    203(非授权信息)
    服务器已成功处理了请求,但返回了可能来自另一来源的信息。
    204(无内容)
    服务器成功处理了请求,但未返回任何内容。
    205(重置内容)
    服务器成功处理了请求,但未返回任何内容。与 204 响应不同,此响应要求请求者重置文档视图(例如清除表单内容以输入新内容)。
    206(部分内容)
    服务器成功处理了部分 GET 请求。
    3xx(已重定向)
    要完成请求,您需要进一步进行操作。通常,这些状态代码是永远重定向的。Google 建议您在每次请求时使用的重定向要少于 5 个。您可以使用网站管理员工具来查看 Googlebot 在抓取您已重定向的网页时是否会遇到问题。诊断下的抓取错误页中列出了 Googlebot 由于重定向错误而无法抓取的网址。
    代码
    说明
    300(多种选择)
    服务器根据请求可执行多种操作。服务器可根据请求者 (User agent) 来选择一项操作,或提供操作列表供请求者选择。
    301(永久移动)
    请求的网页已被永久移动到新位置。服务器返回此响应(作为对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。您应使用此代码通知 Googlebot 某个网页或网站已被永久移动到新位置。
    302(临时移动)
    服 务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。此代码与响应 GET 和 HEAD 请求的 301 代码类似,会自动将请求者转到不同的位置。但由于 Googlebot 会继续抓取原有位置并将其编入索引,因此您不应使用此代码来通知 Googlebot 某个页面或网站已被移动。
    303(查看其他位置)
    当请求者应对不同的位置进行单独的 GET 请求以检索响应时,服务器会返回此代码。对于除 HEAD 请求之外的所有请求,服务器会自动转到其他位置。
    304(未修改)
    自从上次请求后,请求的网页未被修改过。服务器返回此响应时,不会返回网页内容。
    如果网页自请求者上次请求后再也没有更改过,您应当将服务器配置为返回此响应(称为 If-Modified-Since HTTP 标头)。由于服务器可以告诉 Googlebot 自从上次抓取后网页没有更改过,因此可节省带宽和开销

    305(使用代理)
    请求者只能使用代理访问请求的网页。如果服务器返回此响应,那么,服务器还会指明请求者应当使用的代理。
    307(临时重定向)
    服 务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。此代码与响应 GET 和 HEAD 请求的 301 代码类似,会自动将请求者转到不同的位置。但由于 Googlebot 会继续抓取原有位置并将其编入索引,因此您不应使用此代码来通知 Googlebot 某个页面或网站已被移动。
    4xx(请求错误)
    这些状态代码表示,请求可能出错,已妨碍了服务器对请求的处理。
    代码
    说明
    400(错误请求)
    服务器不理解请求的语法。
    401(未授权)
    请求要求进行身份验证。登录后,服务器可能会返回对页面的此响应。
    403(已禁止)
    服务器拒绝请求。如果在 Googlebot 尝试抓取您网站上的有效网页时显示此状态代码(您可在 Google 网站管理员工具中诊断下的网络抓取页面上看到此状态代码),那么,这可能是您的服务器或主机拒绝 Googlebot 对其进行访问。
    404(未找到)
    服务器找不到请求的网页。例如,如果请求是针对服务器上不存在的网页进行的,那么,服务器通常会返回此代码。
    如果您的网站上没有 robots.txt 文件,而您在 Google 网站管理员工具"诊断"标签的 robots.txt 页上发现此状态,那么,这是正确的状态。然而,如果您有 robots.txt 文件而又发现了此状态,那么,这说明您的 robots.txt 文件可能是命名错误或位于错误的位置。(该文件应当位于顶级域名上,且应当名为 robots.txt)。
    如果您在 Googlebot 尝试抓取的网址上发现此状态(位于"诊断"标签的 HTTP 错误页上),那么,这表示 Googlebot 所追踪的可能是另一网页中的无效链接(旧链接或输入有误的链接)。
    405(方法禁用)
    禁用请求中所指定的方法。
    406(不接受)
    无法使用请求的内容特性来响应请求的网页。
    407(需要代理授权)
    此状态代码与 401(未授权)类似,但却指定了请求者应当使用代理进行授权。如果服务器返回此响应,那么,服务器还会指明请求者应当使用的代理。
    408(请求超时)
    服务器等候请求时超时。
    409(冲突)
    服务器在完成请求时发生冲突。服务器必须包含有关响应中所发生的冲突的信息。服务器在响应与前一个请求相冲突的 PUT 请求时可能会返回此代码,同时会提供两个请求的差异列表。
    410(已删除)
    如果请求的资源已被永久删除,那么,服务器会返回此响应。该代码与 404(未找到)代码类似,但在资源以前有但现在已经不复存在的情况下,有时会替代 404 代码出现。如果资源已被永久删除,那么,您应当使用 301 代码指定该资源的新位置。
    411(需要有效长度)
    服务器不会接受包含无效内容长度标头字段的请求。
    412(未满足前提条件)
    服务器未满足请求者在请求中设置的其中一个前提条件。
    413(请求实体过大)
    服务器无法处理请求,因为请求实体过大,已超出服务器的处理能力。
    414(请求的 URI 过长)
    请求的 URI(通常为网址)过长,服务器无法进行处理。
    415(不支持的媒体类型)
    请求的格式不受请求页面的支持。
    416(请求范围不符合要求)
    如果请求是针对网页的无效范围进行的,那么,服务器会返回此状态代码。
    417(未满足期望值)
    服务器未满足"期望"请求标头字段的要求。
    5xx(服务器错误)
    这些状态代码表示,服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。
    代码
    说明
    500(服务器内部错误)
    服务器遇到错误,无法完成请求。
    501(尚未实施)
    服务器不具备完成请求的功能。例如,当服务器无法识别请求方法时,服务器可能会返回此代码。
    502(错误网关)
    服务器作为网关或代理,从上游服务器收到了无效的响应。
    503(服务不可用)
    目前无法使用服务器(由于超载或进行停机维护)。通常,这只是一种暂时的状态。
    504(网关超时)
    服务器作为网关或代理,未及时从上游服务器接收请求。
    505(HTTP 版本不受支持)
    服务器不支持请求中所使用的 HTTP 协议版本。

    css命名为何不推荐使用下划线_

    一直习惯了在命名CSS样式名时使用下划线“_”做为单词的分隔符,这也是在写JS时惯用的写法。

    用过CSS hack的朋友应该知道,用下划线命名也是一种hack,如使用“style”这样的命名,可以让IE外的大部分浏览器忽略这个样式的定义,所以使用“”做为命名时的分隔符是不规范的。在做CSS检查时会出现错误提示,因此要避免使用下划线命名。

    为此得找一个能代替下划线而又合规范的符号,当然不是一定要用这种分隔符之类的,只是个人习惯问题。

    做了个小测试,将下划线分别用了“~”、“$”、“`”、“&”和“-”去代替,结果只有“-”号是可以使用的,而且对JS的支持也正常,看下测试:

    以下为引用的内容:
    -------------------------------CSS---------------------------------
    .try-a{ color:#00f; }
    .try~a{ color:#00f; }
    .try`a{ color:#00f; }
    .try&a{ color:#00f; }
    .try$a{ color:#00f; }

    .try-b{ color:#f00; }
    .try~b{ color:#f00; }
    .try`b{ color:#f00; }
    .try&b{ color:#f00; }

    .try$b{ color:#f00; }

    -----------------------------HTML----------------------------------

    try1
    try2
    try3
    try4
    try5

    ---------------------------------JS----------------------------------
    function b(){
    document.getElementById("a").className="try-b";
    document.getElementById("b").className="try~b";
    document.getElementById("c").className="try`b";
    document.getElementById("d").className="try&b";
    document.getElementById("e").className="try$b";

    }

    结果是“try1”变成了红色,显示正常。不过在CSS定义里,经常会用到ID选择符,如果在页面中的ID命名中使用了“”,就免不了在CSS样式里出现下划线“”了,所以在此还得注意在ID的命名上也要避免使用下划线。

    各种开源协议介绍 BSD、Apache Licence、GPL V2 、GPL V3 、LGPL、MIT

    现今存在的开源协议很多,而经过Open Source Initiative组织通过批准的开源协议目前有58种(http://www.opensource.org/licenses /alphabetical)。我们在常见的开源协议如BSD, GPL, LGPL,MIT等都是OSI批准的协议。如果要开源自己的代码,最好也是选择这些被批准的开源协议。

    这里我们来看四种最常用的开源协议及它们的适用范围,供那些准备开源或者使用开源产品的开发人员/厂家参考。

    BSD开源协议(original BSD license、FreeBSD license、Original BSD license)

    BSD开源协议是一个给于使用者很大自由的协议。基本上使用者可以”为所欲为”,可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。

    但”为所欲为”的前提当你发布使用了BSD协议的代码,或则以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

    1. 如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。
    2. 如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。
    3. 不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。

    BSD 代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对 商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。

    Apache Licence 2.0(Apache License, Version 2.0、Apache License, Version 1.1、Apache License, Version 1.0)

    Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。需要满足的条件也和BSD类似:

    1. 需要给代码的用户一份Apache Licence
    2. 如果你修改了代码,需要再被修改的文件中说明。
    3. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。
    4. 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。

    Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。

    GPL(GNU General Public License)

    我们很熟悉的Linux就是采用了GPL。GPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样。GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代 码做为闭源的商业软件发布和销售。这也就是为什么我们能用免费的各种linux,包括商业公司的linux和linux上各种各样的由个人,组织,以及商 业软件公司开发的免费软件了。

    GPL协议的主要内容是只要在一个软件中使用(”使用”指类库引用,修改后的代码或者衍生代码)GPL 协议的产品,则该软件产品必须也采用GPL协议,既必须也是开源和免费。这就是所谓的”传染性”。GPL协议的产品作为一个单独的产品使用没有任何问题, 还可以享受免费的优势。

    由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础。

    其它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似。

    关于开源协议GPL V2和V3

    单从开源行业的GPL协议上来看,似乎开源linux产品上的一切是可以无条件的开放和共享的,但是从实际的操作来看,在GPL相对的许可授权之下,又有其相对封闭的一面,就这次的GPL v2到GPL v3的修订改版来说,正是GPL协议“封闭”一面的具体体现。

    根据GPL v2的相关规定:只要这种修改文本在整体上或者其某个部分来源于遵循GPL的程序,该修改文本的整体就必须按照GPL流通,不仅该修改文本的源码必须向社 会公开,而且对于这种修改文本的流通不准许附加修改者自己作出的限制。而在GPL v3的修订草案中,不仅要求用户公布修改的源代码,还要求公布相关硬件,恰恰是这一条,由于触及和其他相关数字版权管理(DRM)及其产品的关系,并且也 由于有和开源精神相违的地方,所以备受争议,甚至因此也遭到了有着“LINUX之父”之称的托瓦尔兹的反对。

    从表面上看,GPL v2到GPL v3的升级之困只不过是对协议修订过程中某一条款的分歧,而更为严重的是在两种协议都合法存在的前提下,具体的开源软件或者开源产品的所有者有权选择是遵 循GPL v2协议还是恪守GPL v3协议,因此冲突也就来了,这种冲突正如中科红旗的CTO郑忠源描述的那样:“世界有如此多软件都在GPL v2的约束之下,而自由软件是集合全世界程序员劳动,即使是贡献一行代码,如果该程序员只同意这一代码只遵循GPL v2之下,就不能随便去修改协议。如果计划将软件转移到GPL v3之下,理论上讲,必须征得所有代码人的同意。但是目前还很难确定有多少开发人员愿意转移到新版本之下,如果有的人愿意转,有的人不愿意转,这其中就有 很多的麻烦;而如果多数人都不愿意改变,那这一事情也许就无声无息……”

    通过业内人士的精辟描述,相信大家一定对开源行业和开源软件产品有了一个全新的认识吧,就那熟悉的LINUX系统来说,虽然表面上看起来大家有权按 照自己的需要和目的进行任意的改写重组,但是在诸多的独立程序面前,别人是只能共享使用,而无权修改的,当然获得授权就另当别论了。而就GPL v2到GPL v3的协议升级来说,这种协议的选择上的分歧实际上也是开源行业里一种观念认知上的相左,到底谁的选择是正确的?绝对不是一两句话能说得清的,尤其是在各 种利益交织之下。

    情势之下,开源社区的GPL v2与GPL v3选择之困很现实的会在相当一段时间内给这个行业及其产品造成“兼容问题”,说白了就是两种协议以及两种协议之下的矛盾,不管是人的还是产品的都将会持 续下去,而这种僵持对整个开源行业来说未必是一件好事,最起码从“精神”方面来说这个行业已经在开始分道扬镳。

    LGPL(GNU Lesser General Public License)

    LGPL是GPL的一个为主要为类库使用设计的开源协议。和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同。 LGPL 允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码。这使得采用LGPL协议的开源代码可以被商业软件作为类库引用并 发布和销售。

    但是如果修改LGPL协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生的代码都必须采用LGPL协议。因此LGPL协议的开源 代码很适合作为第三方类库被商业软件引用,但不适合希望以LGPL协议代码为基础,通过修改和衍生的方式做二次开发的商业软件采用。

    GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品

    MIT(MIT)

    MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其他了限制.也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的.

    VIM学习笔记

    vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的。下面的文章翻译自《Learn Vim Progressively》,我觉得这是给新手最好的VIM的升级教程了,没有列举所有的命令,只是列举了那些最有用的命令。非常不错。

    ——————————正文开始——————————

    你想以最快的速度学习人类史上最好的文本编辑器VIM吗?你先得懂得如何在VIM幸存下来,然后一点一点地学习各种戏法。

    Vim the Six Billion Dollar editor

    Better, Stronger, Faster.

    学习 vim 并且其会成为你最后一个使用的文本编辑器。没有比这个更好的文本编辑器了,非常地难学,但是却不可思议地好用。

    我建议下面这四个步骤:

    存活
    感觉良好
    觉得更好,更强,更快
    使用VIM的超能力
    当你走完这篇文章,你会成为一个vim的 superstar。

    在开始学习以前,我需要给你一些警告:

    学习vim在开始时是痛苦的。
    需要时间
    需要不断地练习,就像你学习一个乐器一样。
    不要期望你能在3天内把vim练得比别的编辑器更有效率。
    事实上,你需要2周时间的苦练,而不是3天。

    第一级 – 存活

    安装 vim
    启动 vim
    什么也别干!请先阅读
    当你安装好一个编辑器后,你一定会想在其中输入点什么东西,然后看看这个编辑器是什么样子。但vim不是这样的,请按照下面的命令操作:

    启 动Vim后,vim在 Normal 模式下。
    让我们进入 Insert 模式,请按下键 i 。(陈皓注:你会看到vim左下角有一个–insert–字样,表示,你可以以插入的方式输入了)
    此时,你可以输入文本了,就像你用“记事本”一样。
    如果你想返回 Normal 模式,请按 ESC 键。
    现在,你知道如何在 Insert 和 Normal 模式下切换了。下面是一些命令,可以让你在 Normal 模式下幸存下来:

    i → Insert 模式,按 ESC 回到 Normal 模式.
    x → 删当前光标所在的一个字符。
    :wq → 存盘 + 退出 (:w 存盘, :q 退出) (陈皓注::w 后可以跟文件名)
    dd → 删除当前行,并把删除的行存到剪贴板里
    p → 粘贴剪贴板
    推荐:

    hjkl (强例推荐使用其移动光标,但不必需) →你也可以使用光标键 (←↓↑→). 注: j 就像下箭头。
    :help → 显示相关命令的帮助。你也可以就输入 :help 而不跟命令。(陈皓注:退出帮助需要输入:q)
    你能在vim幸存下来只需要上述的那5个命令,你就可以编辑文本了,你一定要把这些命令练成一种下意识的状态。于是你就可以开始进阶到第二级了。

    当是,在你进入第二级时,需要再说一下 Normal 模式。在一般的编辑器下,当你需要copy一段文字的时候,你需要使用 Ctrl 键,比如:Ctrl-C。也就是说,Ctrl键就好像功能键一样,当你按下了功能键Ctrl后,C就不在是C了,而且就是一个命令或是一个快键键了,在VIM的Normal模式下,所有的键就是功能键了。这个你需要知道。

    标记:

    下面的文字中,如果是 Ctrl-λ我会写成 <C-λ>.
    以 : 开始的命令你需要输入 回车,例如 — 如果我写成 :q 也就是说你要输入 :q.
    第二级 – 感觉良好

    上面的那些命令只能让你存活下来,现在是时候学习一些更多的命令了,下面是我的建议:(陈皓注:所有的命令都需要在Normal模式下使用,如果你不知道现在在什么样的模式,你就狂按几次ESC键)

    各种插入模式
    a → 在光标后插入
    o → 在当前行后插入一个新行
    O → 在当前行前插入一个新行
    cw → 替换从光标所在位置后到一个单词结尾的字符
    简单的移动光标
    0 → 数字零,到行头
    ^ → 到本行第一个不是blank字符的位置(所谓blank字符就是空格,tab,换行,回车等)
    $ → 到本行行尾
    g_ → 到本行最后一个不是blank字符的位置。
    /pattern → 搜索 pattern 的字符串(陈皓注:如果搜索出多个匹配,可按n键到下一个)
    拷贝/粘贴 (陈皓注:p/P都可以,p是表示在当前位置之后,P表示在当前位置之前)
    P → 粘贴
    yy → 拷贝当前行当行于 ddP
    Undo/Redo
    u → undo
    → redo
    打开/保存/退出/改变文件(Buffer)
    :e <path/to/file> → 打开一个文件
    :w → 存盘
    :saveas <path/to/file> → 另存为 <path/to/file>
    :x, ZZ 或 :wq → 保存并退出 (:x 表示仅在需要时保存,ZZ不需要输入冒号并回车)
    :q! → 退出不保存 :qa! 强行退出所有的正在编辑的文件,就算别的文件有更改。
    :bn 和 :bp → 你可以同时打开很多文件,使用这两个命令来切换下一个或上一个文件。(陈皓注:我喜欢使用:n到下一个文件)
    花点时间熟悉一下上面的命令,一旦你掌握他们了,你就几乎可以干其它编辑器都能干的事了。但是到现在为止,你还是觉得使用vim还是有点笨拙,不过没关系,你可以进阶到第三级了。

    第三级 – 更好,更强,更快

    先恭喜你!你干的很不错。我们可以开始一些更为有趣的事了。在第三级,我们只谈那些和vi可以兼容的命令。

    更好
    下面,让我们看一下vim是怎么重复自己的:

    . → (小数点) 可以重复上一次的命令
    N → 重复某个命令N次
    下面是一个示例,找开一个文件你可以试试下面的命令:

    2dd → 删除2行
    3p → 粘贴文本3次
    100idesu [ESC] → 会写下 “desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu desu “
    . → 重复上一个命令—— 100 “desu “.
    3. → 重复 3 次 “desu” (注意:不是 300,你看,VIM多聪明啊).
    更强
    你要让你的光标移动更有效率,你一定要了解下面的这些命令,千万别跳过。

    NG → 到第 N 行 (陈皓注:注意命令中的G是大写的,另我一般使用 : N 到第N行,如 :137 到第137行)
    gg → 到第一行。(陈皓注:相当于1G,或 :1)
    G → 到最后一行。
    按单词移动:
    w → 到下一个单词的开头。
    e → 到下一个单词的结尾。

    如果你认为单词是由默认方式,那么就用小写的e和w。默认上来说,一个单词由字母,数字和下划线组成(陈皓注:程序变量)

    如果你认为单词是由blank字符分隔符,那么你需要使用大写的E和W。(陈皓注:程序语句)

    Word moves example

    下面,让我来说说最强的光标移动:

    % : 匹配括号移动,包括 (, {, [. (陈皓注:你需要把光标先移到括号上)

    • 和 #: 匹配光标当前所在的单词,移动光标到下一个(或上一个)匹配单词(*是下一个,#是上一个)
      相信我,上面这三个命令对程序员来说是相当强大的。

    更快
    你一定要记住光标的移动,因为很多命令都可以和这些移动光标的命令连动。很多命令都可以如下来干:

    例如 0y$ 命令意味着:

    0 → 先到行头
    y → 从这里开始拷贝
    $ → 拷贝到本行最后一个字符
    你可可以输入 ye,从当前位置拷贝到本单词的最后一个字符。

    你也可以输入 y2/foo 来拷贝2个 “foo” 之间的字符串。

    还有很多时间并不一定你就一定要按y才会拷贝,下面的命令也会被拷贝:

    d (删除 )
    v (可视化的选择)
    gU (变大写)
    gu (变小写)
    等等
    (陈皓注:可视化选择是一个很有意思的命令,你可以先按v,然后移动光标,你就会看到文本被选择,然后,你可能d,也可y,也可以变大写等)
    第四级 – Vim 超能力

    你只需要掌握前面的命令,你就可以很舒服的使用VIM了。但是,现在,我们向你介绍的是VIM杀手级的功能。下面这些功能是我只用vim的原因。

    在当前行上移动光标: 0 ^ $ f F t T , ;
    0 → 到行头
    ^ → 到本行的第一个非blank字符
    $ → 到行尾
    g_ → 到本行最后一个不是blank字符的位置。
    fa → 到下一个为a的字符处,你也可以fs到下一个为s的字符。
    t, → 到逗号前的第一个字符。逗号可以变成其它字符。
    3fa → 在当前行查找第三个出现的a。
    F 和 T → 和 f 和 t 一样,只不过是相反方向。
    Line moves
    还有一个很有用的命令是 dt" → 删除所有的内容,直到遇到双引号—— "。

    区域选择 a 或 i
    在visual 模式下,这些命令很强大,其命令格式为

    a 和 i

    action可以是任何的命令,如 d (删除), y (拷贝), v (可以视模式选择)。
    object 可能是: w 一个单词, W 一个以空格为分隔的单词, s 一个句字, p 一个段落。也可以是一个特别的字符:"、 '、 )、 }、 ]。
    假设你有一个字符串 (map (+) ("foo")).而光标键在第一个 o 的位置。

    vi" → 会选择 foo.
    va" → 会选择 "foo".
    vi) → 会选择 "foo".
    va) → 会选择("foo").
    v2i) → 会选择 map (+) ("foo")
    v2a) → 会选择 (map (+) ("foo"))
    Text objects selection

    块操作:
    块操作,典型的操作: 0 I-- [ESC]

    ^ → 到行头
    → 开始块操作
    → 向下移动 (你也可以使用hjkl来移动光标,或是使用%,或是别的)
    I-- [ESC] → I是插入,插入“--”,按ESC键来为每一行生效。
    Rectangular blocks

    在Windows下的vim,你需要使用 而不是 , 是拷贝剪贴板。

    自动提示: 和
    在 Insert 模式下,你可以输入一个词的开头,然后按 或是,自动补齐功能就出现了……

    Completion

    宏录制: qa 操作序列 q, @A, @@
    qa 把你的操作记录在寄存器 a。
    于是 @A 会replay被录制的宏。
    @@ 是一个快捷键用来replay最新录制的宏。
    示例

    在一个只有一行且这一行只有“1”的文本中,键入如下命令:

    qaYpq→
    qa 开始录制
    Yp 复制行.
    增加1.
    q 停止录制.
    @A → 在1下面写下 2
    @@ → 在2 正面写下3
    现在做 100@@ 会创建新的100行,并把数据增加到 103.
    Macros

    可视化选择: v,V,
    前面,我们看到了 的示例 (在Windows下应该是),我们可以使用 v 和 V。一但被选好了,你可以做下面的事:

    J → 把所有的行连接起来(变成一行)
    < 或 > → 左右缩进
    = → 自动给缩进 (陈皓注:这个功能相当强大,我太喜欢了)
    Autoindent

    在所有被选择的行后加上点东西:

    选中相关的行 (可使用 j 或 或是 /pattern 或是 % 等……) $ 到行最后 A, 输入字符串,按 ESC。 Append to many lines

    分屏: :split 和 vsplit.
    下面是主要的命令,你可以使用VIM的帮助 :help split. 你可以参考本站以前的一篇文章VIM分屏。

    :split → 创建分屏 (:vsplit创建垂直分屏)

    : dir就是方向,可以是 hjkl 或是 ←↓↑→ 中的一个,其用来切换分屏。
    _ (或 |) : 最大化尺寸 (| 垂直分屏)
    + (或 -) : 增加尺寸
    Split

    结束语

    上面是作者最常用的90%的命令。
    我建议你每天都学1到2个新的命令。
    在两到三周后,你会感到vim的强大的。
    有时候,学习VIM就像是在死背一些东西。
    幸运的是,vim有很多很不错的工具和优秀的文档。
    运行vimtutor直到你熟悉了那些基本命令。
    其在线帮助文档中你应该要仔细阅读的是 :help usr_02.txt.
    你会学习到诸如 !, 目录,寄存器,插件等很多其它的功能。
    学习vim就像学弹钢琴一样,一旦学会,受益无穷。

    ——————————正文结束——————————

    对于vi/vim只是点评一点:这是一个你不需要使用鼠标,不需使用小键盘,只需要使用大键盘就可以完成很多复杂功能文本编辑的编辑器。不然,Visual Studio也不就会有vim的插件了。

    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.