NO END FOR LEARNING

Writing blog if you feel tired | 学海无涯 苦写博客

CSS后代选择器以及选择器特殊性

| Comments

常用的重要选择器规则:

element,element div,p 选择所有 div 元素和所有 p 元素。
element element div p 后代选择器:选择 div 元素内部的所有 p 元素。
element>element div>p 子选择器:选择父元素为 div 元素的所有 p 元素。
element+element div+p 第一个子元素选择器:选择紧接在 div 元素之后的所有 p 元素。

后代选择器

后代选择器(descendant selector)又称为包含选择器。后代选择器可以选择作为某元素后代的元素。

我们可以定义后代选择器来创建一些规则,使这些规则在某些文档结构中起作用,而在另外一些结构中不起作用。 举例来说,如果你希望只对 h1 元素中的 em 元素应用样式,可以这样写:

1
h1 em {color:red;}

上面这个规则会把作为 h1 元素后代的 em 元素的文本变为 红色。其他 em 文本(如段落或块引用中的 em)则不会被这个规则选中:

1
2
<h1>This is a <em>important</em> heading</h1>
<p>This is a <em>important</em> paragraph.</p>

在后代选择器中,规则左边的选择器一端包括两个或多个用空格分隔的选择器。选择器之间的空格是一种结合符(combinator)。每个空格结合符可以解释为“… 在 … 找到”、“… 作为 … 的一部分”、“… 作为 … 的后代”,但是要求必须从右向左读选择器。 因此,h1 em 选择器可以解释为 “作为 h1 元素后代的任何 em 元素”。如果要从左向右读选择器,可以换成以下说法:“包含 em 的所有 h1 会把以下样式应用到该 em”。

关于后代选择器有一个常被忽略的方面,即两个元素之间的层次间隔可以是无限的。例如,如果写作ul em,这个语法就会选择从u1元素继承的所有em元素,而无论em的嵌套层次有多深。

子选择器

某些情况下,可能并不想选择一个任意的后代元素,而是希望缩小范围,只选择另一个元素的子元素(不是所有后代元素)。可以使用子结合符,即大于号(>)

1
h1 > strong {color: red;}

特殊性

如果有多个选择器都满足同一个元素,即冲突了,怎么知道哪一个规则更强?

答案在于每个选择器的特殊性。对于每个规则,用户代理会计算选择器的特殊性,并将这个特殊性附加在规则中的各个声明。如果一个元素有两个或者多个冲突的属性声明,那么有最高特殊性的声明就会胜出。

选择器的特殊性由选择器本身的组件确定。特殊性表述为4个部分,0,0,0,0

1.对于选择器中给定的各个ID属性,加 0,1,0,0 2.对于选择器中给定的各个类元素,属性选择器或伪类,加 0,0,1,0 3.对于选择器中给定的各个元素和伪元素,加0,0,0,1 4.结合符和通配选择器对特殊性没有任何贡献

1
2
3
4
5
6
h1 {color: red;} 0,0,0,1
p em {color: purple;} 0,0,0,2
.grape {color: purple} 0,0,1,0
*.bright {color: yellow} 0,0,1,0
p.bright em.dark {color: maroon} 0,0,2,2
div#sidebar *[href] {color: silver} 0,1,1,1

第五条规则强于第二条

0011 > 0001 0101 > 0017

内联样式的特殊性 我们已经见过以0开头的特殊性,所以你可能会奇怪为什么会有这些特殊性。一般地,第一个0是为内联样式声明保留的,它比所有其他声明的特殊性都高,内联样式的特殊性是1,0,0,0

!important 重要性规则

有时某个声明可能非常重要,超过了所有其他声明。CSS2.1称之为重要声明,并允许在这些声明的结束分号之前插入!important来标识。

1
p.dark {color: #333 !important; background: white;}

必须正确地放置!important,否则声明将无效,它应该总是放在声明的最后,即分号之前。如果一个属性的值包含多个关键字,则必须放在最后一个关键词的后面,比如font:sss,sss !important;

标志位!important的声明并没有特殊的特殊性值,不过要与非重要声明分开考虑。实际上,所有!important声明会分组在一起,重要声明的特殊性冲突会在重要声明内部解决,而不会与非重要声明相混肴。类似的,非重要声明也归为一组,使用特殊性来解决冲突。如果一个重要声明和一个非重要声明冲突,胜出的总是重要声明。

1.《css权威指南》

理解设计RESTful API - 资源、表述和HTTP协议语义

| Comments

什么是资源?什么是表述?

就本质而言,任何足够重要并被引用的事物都可以是资源。如果你的用户“想要建立指向它的超文本链接,指出或者反对关于它的断言,获取或者缓存它的表述,共另外的表述引用它的全部或者部分,给它增加注释信息,或者对它执行某些操作”,(源自《万维网的架构》),你都应该将它定义为资源。

每个资源必须拥有URL,在web上,我们使用URL来为每个资源提供一个全球唯一的地址,将一个事物赋以URL,它就会成为一个资源。

石榴可以是一个资源,但是你不可能通过互联网传输它,数据库中的一条记录可以是一个资源,并且可以通过互联网传输。

当客户端对一个资源发起一个Get请求的时候,服务器会以一种有效的方式提供一个采集了资源信息的文档作为回应。这种资源信息的文档就是一种表述,一种以机器可读的方式对资源当前的状态进行说明。

资源有多重表述

一个资源可以有多种表述。比如,有的资源可以有整体概括性的表述,也可以有面面俱到的详细表述,又或者可能以JSON格式或者XML格式来表述同一个资源。

约束 - HTTP协议语义

尽管任何事物都可以成为一个资源,但是客户端并不能随心所欲地对资源进行任意的操作。所能进行的操作是有规定的。在一个RESTful系统里,客户端和服务器端只能通过相互发送遵循预定义协议的消息来进行交互。在Web API的世界里,该协议就是HTTP。

在设计Web API时,严格遵守HTTP协议语义是设计好的API的重要基础。

GET请求

客户端通过发送Get请求来获取某个URL所标示的资源的表述。Get被定义为安全的HTTP方法。它仅仅是对信息的一次请求。向服务器发送一条Get请求对资源的影响应该和没有发送一样。

DELETE请求

发送DELETE请求,客户端希望服务器将资源销毁,并且以后再也不会跳到它。当Get请求再次访问一个已经销毁的资源,服务器应该返回错误响应码,比如404(Not Found)。Delete不是一个安全的方法,它会改变资源的状态,但是DELETE方法有另外一个很重要的属性,就是幂等性。当你发送一个DELETE请求后,资源就永久性的消失了,即便之后,再次发送相同的DELETE请求,也许你会收到404的错误码,但是第二次发送后和第一次发送后,资源的状态是一致的,仍然不存在。

幂等性是一个很重要的特性,因为互联网的不稳定性,假设发送的一个Delete请求,因为连接超时,你并没有收到响应,所以你无法知道发送的Delete请求是否顺利完成,这时你也许会发送第二次Delete请求。幂等性保证了执行两次Delete请求并不会比执行一次Delete请求给资源带来更多的影响。

POST-to-Append请求

为什么是Post-to-Append而不是Post呢?因为Post方法可以做两件事情,第一件事情就是Post-to-Append,第二件事情叫做overloaded post。我们先看POST-to-Append,向某个资源发送一条Post请求用以在该资源的下一级中创建新的资源,当客户端发送一个POST-to-Append请求时,它会在请求的实体消息体中添加所希望创建的资源的表述信息并发给服务器。Post方法既不安全也不幂等,如果发送多次Post请求,就会创建多个资源。

PUT请求

Put请求用于修改资源的状态。客户端一般会通过Get请求获取表述,然后对其进行修改,最后再将修改后的资源表述作为PUT请求的负载数据发送回去。PUT请求也是幂等的,无论发送多少次PUT请求,结果都和第一次发送PUT请求一样。


以上4种请求,我们最常见也是使用最频繁的请求。接下来要介绍的请求,虽然见的不多,但是当你了解后,你会觉得它非常有用。

PATCH请求

表述的信息量可能非常大。虽然,我们可以使用PUT请求来修改资源,但是如果只想修改资源状态的部分,或者说很少一部分,才PUT就会造成极大的资源浪费,这对于移动应用所使用的Web API设计是非常重要的。和将完整信息发送过去的PUT方法不同,PATCH方法将一个“diff”的表述放在请求的负载数据中发送给服务器。

HEAD请求

Head方法是和Get方法一样的安全方法。服务器应该和处理Get方法一样除了Head方法,但是Head方法不需要发送实体消息,只需要发送HTTP状态码和报头。

OPTIONS请求

OPTIONS是HTTP的原生探索机制。一个OPTIONS请求的返回结果包含一个HTTP Allow报头,这个报头展示了这个资源所支持的所有HTTP方法。

肮脏的Overloaded POST请求

POST不仅仅被用于创建新的资源,在用浏览器上网的时候,POST也被用于传输任何形式的变化,它将PUT、DELETE、PATCH、LINK和UNLINK所有的方法混合成一个方法。

比如,在页面有一个表单对用户的基本信息进行修改,它是一个POST请求,但是从语义上,它更像是一个PUT,但这完全是合法的,任何数据作为POST请求的一部分发出去,不论是出于什么目的,这都是合法的。这导致POST请求没有任何语义。由于重载后的POST请求可以用来完成任何事情,所以这种POST方法既不安全也不幂等。


好的API不应该依靠文档来维护它的使用方式,就好像是优秀的代码,不需要注释来考诉你它是干什么,合理的协议语义的使用会帮助API实现基本的自我描述,虽然这还远远不够,但它最起码是互联网上大家都遵守的约束。

参考资料:
1. RESTful Web AIPs