xml地图|网站地图|网站标签 [设为首页] [加入收藏]
理解CSS属性值语法,AngularJs前端架构
分类:web前端

理解CSS属性值语法

2016/08/12 · CSS · 属性值

本文由 伯乐在线 - 殊 翻译,艾凌风 校稿。未经许可,禁止转载!
英文出处:Russ Weakley。欢迎加入翻译组。

W3C 使用特定的语法来定义所有可能在 CSS 属性中使用的值。如果你曾经看过 CSS 规范,你可能已经见过这种语法的使用 – 比如 border-image-slice 语法。让我们来看看:

CSS

<'border-­image-­slice'> = [<number> | <percentage>]{1,4} && fill?

1
<'border-­image-­slice'> = [<number> | <percentage>]{1,4} && fill?

这个语法可能很难理解-如果你不知道其中的各个符号和他们是怎样生效的话。但是,这是值得花时间去学习的。如果你理解了 W3C 是怎样定义这些属性值,你就能理解 W3C 的任何 CSS 规范。

澳门新葡亰手机版 1

用“MEAN”技术栈开发web应用(一)AngularJs前端架构

2015/09/09 · CSS, HTML5, JavaScript · 1 评论 · MEAN

原文出处: 吕大豹   

行内格式化上下文中的各种高度计算

2015/10/11 · 澳门新葡亰手机版,CSS · 高度

原文出处: HaoyCn   

前言碎碎语:标题问题在昨天困扰了笔者很久很久,早上把问题提到了各网络也暂时没有回复。因为明天要早起飞异地参加一场校招面试,笔者还是很紧张的,但奈何问题不解决寝食难安……所以还是卯起劲重新思考这个问题,算是暂时有了一个自己比较认可以及清晰的答案,与各位读者分享。如您有不同观点想法意见建议,恳请斧正!

正式探讨之前,我们观察一个现象(在 Chrome 下的表现,其他浏览器下的表现和计算可能有细微差别):

澳门新葡亰手机版 2

上图对应的 HTML 是(之后的探讨均基于此):

<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>Line Height</title> <style> body { margin: 0; font: 32px/1 'Microsoft YaHei'; } div { width: 400px; margin: 30px auto; outline: 1px solid black; background: #008E59; } img { height: 80px; margin-top: 10px; } </style> </head> <body> <div> <span>Some Text</span> <img src="picture.jpg" alt=""/> </div> </body> </html>

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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Line Height</title>
<style>
body {
    margin: 0;
    font: 32px/1 'Microsoft YaHei';
}
div {
    width: 400px;
    margin: 30px auto;
    outline: 1px solid black;
    background: #008E59;
}
img {
    height: 80px;
    margin-top: 10px;
}
</style>
</head>
<body>
    <div>
        <span>Some Text</span>
        <img src="picture.jpg" alt=""/>
    </div>
</body>
</html>

我们来计算下 DIV 和 SPAN 的高度

JavaScript

document.getElementsByTagName('div')[0].offsetHeight //93 document.getElementsByTagName('span')[0].offsetHeight //42

1
2
3
4
document.getElementsByTagName('div')[0].offsetHeight
//93
document.getElementsByTagName('span')[0].offsetHeight
//42

对于此图,笔者产生如下疑问:

  • line-height  为 32px,为何 SPAN 的高度为 42px?
  • DIV 的高度 93px,比 IMG 高度加外边距 90px 以及 SPAN 高度 42px 都要大,如何计算的?
  • 图片和文本下的空白(即便没有文本一样存在)是如何产生的?

假设我们把 IMG 删除,HTML 部分改为:

<body> <div> <span>Some Text</span> </div> </body>

1
2
3
4
5
<body>
    <div>
        <span>Some Text</span>
    </div>
</body>

此时来计算:

JavaScript

document.getElementsByTagName('div')[0].offsetHeight //32 document.getElementsByTagName('span')[0].offsetHeight //42

1
2
3
4
document.getElementsByTagName('div')[0].offsetHeight
//32
document.getElementsByTagName('span')[0].offsetHeight
//42

新问题又来了:

  • DIV 的子元素高度为 42px,为何没有“撑起” DIV 的高度?

以上问题就是本文要探讨的了。覆盖了五个知识点:

  1. 行内盒(或行内不可替换元素)的高度
  2. 行内可替换元素的高度
  3. 行盒的高度
  4. 行距与行高
  5. 建立行内格式化上下文的块盒的 auto 高度

所以在探讨之前,笔者已假设您知道这些概念:行内盒、行内不可替换元素、行内可替换元素、行盒、行内格式化上下文。如果您还有点不清楚,我们可以快速补习下:

可替换元素、不可替换元素

简单地讲,可替换元素是指须根据其标签和属性来决定具体显示内容的元素,如本文中会探讨的 IMG 元素,其具体显示内容由  src 等属性决定; 不可替换元素则是内容直接呈现的元素。如本文会探讨的 DIV 和 SPAN 等。

块盒

此概念是块格式化上下文的内容,要解释起来就更复杂啦,笔者粗陋地给您一个描述:块盒通常是  display: block 的不可替换元素。

行内级元素、行内级盒、行内盒、行内格式化上下文

display: inline|inline-table|inline-block  产生行内级元素。行内级元素生成行内级盒,而这些盒会参与行内格式化上下文。

display 值是  inline 的不可替换元素会生成一个行内盒。

不是行内盒的行内级盒被称为原子行内级盒。

澳门新葡亰手机版 3

行盒

在行内格式化上下文中,盒从包含块的顶部一个接一个地水平摆放。包含了一行里所有盒的矩形区域被称为行盒。一个段落就是多个行盒的垂直堆叠。

因此,我们可以得到下图(大致描摹):

澳门新葡亰手机版 4

现在开始计算!

巴科斯范式

我们将从巴科斯范式开始,因为这会帮助我们理解 W3C 的属性值语法。 巴科斯范式( BNF )是一种用来描述计算机语言语法的符号集。它的设计是明确的,所以对于如何表示语言这方面不存在分歧或歧义。 如今广泛使用的是巴科斯范式的扩展和编译版本,包括扩展巴科斯范式( EBNF )和扩充巴科斯范式( ABNF )。 一个 BNF 规范是一组按照下面的方式书写的规则:

CSS

<symbol> ::= __expression__

1
<symbol>  ::=  __expression__

左边的部分总是一个非终结符,随后是一个 ::= 符号,这个符号的意思是“可以被替换为”。右边是一个 __expression__ ,包含一个或更多用来推导左边符号的含义的符号。 BNF 的基本规范说,“左边的任何都可以被右边的替换”。

前言

不知何时突然冒出“MEAN技术栈”这个新词,听起来很牛逼的样子,其实就是我们已经熟悉了的近两年在前端比较流行的技术,mongodb、express、angularjs、nodejs,由于这几项技术涵盖了从前端到后端再到数据库,可以用他们完整的开发一个web应用了,所以成了一个非常牛逼的组合,颇有当年LAMP的气势。前端要从切图仔迈向全栈的路上,这几门技术必须得有所涉猎。本系列文章利用自己虚构的一个小项目为例,对“使用MEAN技术栈开发web应用”做一个入门级的介绍。

1 行内可替换元素和文档流内行内块可替换元素高度计算

W3C 有明确规范,如下:

如果  height 和  width  计算值均为 auto 且该元素有固有高度,那么该固有高度为 height 使用值。

否则,如果  height 计算值为  auto ,且该元素有一个固有比例,则  height 的使用值为:

width 使用值 / 固有比例

否则,如果  height 计算值为  auto ,且该元素有固有高度,那么该固有高度为  height 使用值。

否则,如果  height 计算值为  auto ,但以上情况均不符合,那么  height  的使用值必须设定为一个最大矩形的高度,该矩形比例为2:1,高度不超过150px,且宽度不大于设备宽度。

因此,在我们的实例中,IMG 盒的高度为 80+10 = 90px。

非终结符和终结符

非终结符是可以被替换或再细分的符号。在 BNF 中,非终结符出现在 < > 中。在下面的例子中,<integer><digit>是非终结符。

CSS

<integer> ::= <digit> | <digit><integer>

1
<integer>  ::=  <digit> | <digit><integer>

终结符就代表一个值不可被替换或者再细分。在下面的例子中,所有的数值都是终结符。

CSS

<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

1
<digit>  ::=  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

AngularJs的争议

angular,简称ng,是google出品的优秀框架,在2013~2014年大红大紫,但是国内好像慢一拍,我从2015年才看到使用ng的项目大量出现。ng自出现伊始就有人诟病太难上手了,完全不同的开发方式,团队开发更是不知道如何组织代码。不过随着jquery这位老大哥逐渐被抛弃,大家开始慢慢接受mvvm这样的编程思维。然而一个不好的消息是,ng团队打算重构的angular2.0版本要发生重大变革,与1.0不能同日而语,虽然官方有1.0向2.0迁移的方案,但额外的工作总是不太好的,而且使用2.0还要付出更多的学习成本。

再加上今年又有react这个实力派雄起,ng的风头顿时被抢过去了,人们又开始研究react下的编程方式。不过我估计react的真正实用也得等到一两年后。眼下angular1.x也仍然是一个不错的选择。尽管有2.0的变革,但是1.4还是一个稳定版本,我们使用稳定版本肯定是不会有问题的。

所以我的结论是,但用无妨,不会存在白学了这种事情,就算将来angular1.x废弃了,你学到的编程思维还是在的。

本文讨论如何使用AngularJs进行前端的架构,对于ng的基础知识不做讲解,需要了解的同学可以看我之前写过的一个系列

2 行内盒的高度计算

“高度”一词在这里颇有歧义,笔者认为,总共可以有三种概念需要辨析:

  • 行内盒的内容区域高度
  • 行内盒的盒高度
  • 计算行盒高度时的行内盒的盒高度

您可能对第二和第三解释抱有疑问,但我们先搁置怀疑,把清楚明白的东西先解决。

当我们用 JavaScript 去获取一个行内盒的 offsetHeight 值时,如我们上面所做的:

JavaScript

document.getElementsByTagName('span')[0].offsetHeight

1
document.getElementsByTagName('span')[0].offsetHeight

笔者将此高度称作“行内盒的盒高度”,类比于我们所熟知的块盒盒高度。其计算值是:

内容区域高度 + 上下边框 + 上下内边距 = 行内盒的盒高度

边框和内边距的宽度默认为 0,否则为我们自己指定,但“内容区域高度”是怎么计算的呢?

W3C 这么说:

height 不适用。内容区域的高度应基于字体,但本规范没有指定如何。用户代理可能,比如说,使用行高盒 EM-Box 或字体的最大上端部 Ascender 和下端部 Descender。(后一种会确保有部分在行高盒之上或之下的字符仍然落在内容区域内,但会导致不同字体有大小不一的盒子;前者则确保作者可以控制相对于 line-height 的背景设计,但也导致字符绘制在其内容区域之外。)

言下之意:

  1. height 属性无效
  2. 行内盒内容区域高度在规范里面没有定义,浏览器可以自己折腾

既然规范没有明确规定计算,我们让浏览器实测一下。笔者浏览器测试如下:

  • Chrome 42
  • IE11 42
  • Firefox 43

如果我们更改字体,假设应用如下 CSS

CSS

body { font-family: Simsun; }

1
body { font-family: Simsun; }
  • Chrome 33
  • IE11 37
  • Firefox 35

而如果我们修改 line-height ,以上结果均不受影响。

笔者也曾疑惑,这个 offsetHeight 就是内容区域高度吗?答案:是。笔者的验证方法是基于 W3C 如下规定:

尽管不可替换元素的外边距、边框以及内边距不纳入行盒的计算,它们仍然渲染在行内盒的周围。这意味着如果  line-height  指定的高度小于被包含盒的内容高度,内边距和边框的背景和颜色可能“流进”毗邻的行盒。用户代理应当按文档顺序渲染这些盒。这会造成后面的盒的边框绘制在前面盒的边框和文本上。

您可以用以下代码实测,会发现红色行内盒的背景溢出到了黑色行内盒所在的行盒。

<div> <span style="background:red">Some Text</span> <br/> <span style="background:rgba(0,0,0,.5)">Some Text</span> </div>

1
2
3
4
5
<div>
    <span style="background:red">Some Text</span>
    <br/>
    <span style="background:rgba(0,0,0,.5)">Some Text</span>
</div>

可知内容区域高度,即行内盒没有内边距和边框时的  offsetHeight 。

因此总结论是:

行内盒的内容区域高度计算没有统一的标准,不同的字体或者不同的浏览器都可能导致不同的结果,且其高度与  line-height 无关。

由此我们无法确切地获得一个跨浏览器的行内盒的内容区域高度。同样我们也无法确切获得一个跨浏览器的行内盒高度(因为其计算式里面就包括了不定变量内容区域高度)。

但问题来了,不同浏览器都采用不同的行内盒内容区域高度,又如何能统一计算行盒以及块容器的高度呢?这个问题便导致了笔者在上面所提到的“计算行盒高度时的行内盒的盒高度”概念。

我们进入下一个话题,行盒高度计算。

CSS 属性值语法

虽然 W3C 的 CSS 属性值语法是基于 BNF 的概念,但它还是有差异的。相似之处在于它开始于非终结符,不同之处在于它使用“组合值”这种表达式来描述符号。 在下面的例子中,<line-width>是一个非终结符,<length>thinmediumthick 就是组合值。

CSS

<line-­width> = <length> | thin | medium | thick

1
<line-­width>  =  <length> | thin | medium | thick

练手项目简介

为了系统的学习“MEAN”技术栈,我虚构了一个小项目,先做一个介绍。

QuestionMaker,是一个用于生成调查问卷的系统,用户可以编辑试题(选择题、填空题),并可以实时预览编辑结果。然后还可以编辑一份试卷,为试卷添加试题,然后保存为一分完整的调查问卷。有点类似于调查派。先上一张截图吧:

澳门新葡亰手机版 5

项目的功能主要是CRUD操作,所以非常适合angular的应用场景,双向绑定对于实现实时预览这样的功能简直是信手拈来。

项目的前后端是完全分离的,后端不渲染页面,只提供数据接口,前端使用ng的动态模板来渲染页面,通过ajax请求来获取所需数据。

项目我已经开源到github,有兴趣的同学可以查看:

3 行盒高度计算

根据规范,行盒的高度决定如下:

  1. 计算行盒内每个行内级盒的高度。对于可替换元素、行内块元素以及行内表格元素,高度是其外边距盒的高度;对于行内盒,高度是其  line-height 。
  2. 行内级盒根据其  vertical-align  属性垂直对齐。如果它们对齐  top 或  bottom ,它们必须以能最小化行盒高度的方式对齐。如果这些盒足够高,则有多种解决方案并且 CSS2.1 没有规定此行盒的基线的位置。
  3. 行盒高度是最上盒顶部到最下盒底部的距离。

懂了:W3C 尽管允许浏览器有自己的行内盒内容区域计算方式,但统一了一个行盒高度的计算方式:

计算行盒的高度时,针对行内盒,高度直接取  line-height 。行内盒可以有边框、内边距、外边距,然而跟行盒的高度完全没关系!

根据此规定,我们很快可以得出,计算行盒高度时,SPAN 盒的高度取 32px。

接着,由于我们的  vertical-align 是默认的  baseline ,因此,应当把盒的基线同父盒的基线对齐。如果盒没有基线,对齐盒的下外边距边缘与父盒的基线。也就是说,把 SPAN 盒的基线同 DIV 盒的基线对齐,把 IMG 盒的下外边距边缘同 DIV 盒的基线对齐。

下图是字体的基线、上下端线等位置信息

澳门新葡亰手机版 6

图片来源:

笔者作图如下:

澳门新葡亰手机版 7

假设我们设 DIV 盒的基线是 0,则 IMG 盒的下边缘同 DIV 盒基线对齐;上边缘(上外边距边缘顶部)在高于基线 90px 处。而 SPAN 盒由于其基线对齐 DIV 盒基线,故其行盒下边缘略低于基线。

整个行盒的高度即 IMG 盒上边缘到 SPAN 盒下边缘。假设没有 IMG 元素,则高度为 SPAN 盒的  line-height 。

但读者您可能注意到了,29 和 -3 是怎么得来的呢?下面,笔者带您算!

组合值

有四种类型的组合值:关键词,基本数据类型,属性数据类型和非属性数据类型。

前端目录结构

用ng来构建一个项目应该如何安排目录结构呢?为了不人工增加复杂度,我这里没有用bower来管理依赖库,也没有其他文章中介绍的那样用yeoman来生成项目,只是单纯的手动来创建目录,这样可以把我们的注意力集中到项目的核心上,目录结构是这样的:

前端的代码都在src目录下,包括入口文件index.html,这样方便我们后续做合并压缩等编译工作,编译后的文件可以一并放入dist目录下。

4 行距和行高计算

29 和 -3 两值是在计算行距和行高后得来的。我们先来看规范:

CSS 假设每种字体都由字体特性来指定一个基线之上的特性高度和之下的特性深度。本节中我们用A表示(给定字体给定字号的)高度,用D表示深度。同时定义 AD = A + D,即从顶部到底部的距离。(参见下面如何找到TrueType和OpenType字体的A和D)注意该字体的这些特性是就整个而言的,无须对应任何个别字符的上端部和下端部。

用户代理必须在一个不可替换行内盒中依照字符的相应基线对齐各个字符。接着,就每个字符来决定A和D。注意单个元素的字符可能来自于不同字体因此不见得所有的A和D一样。如果行内盒完全不包含字符,则被视为包含了一个具有元素首个可用字体的A和D的支柱(一个零宽度的不可见字符)。

接着对每个字符添加行距L,其中 L = line-height - AD 。行距的一般添加到A之上,另一半添加到D之下,从而赋予字符以及其行距一个基线之上的完整高度 A’ = A + L/2,以及完整深度 D’ = D+ L/2。

注意。L可能为负。

包含了所有字符以及字符两侧半行距的行内盒的高度正是  line-height 。

我们在上述规定中接触到了这些概念:特性高度 A,特性深度 D,顶部到底部距离 AD,完整高度 A’,完整深度 D’,行距 L。

关于特性值,笔者 Google 到一个网站,推荐读者使用:

不得不吐槽下,国内真的很难找到这样专业精致的字体网站(也可能是我的打开方式不对 >_<)。

好,我们可以获得我们实例中 Microsoft YaHei 的字体特性了:Dcsender -536;Height 2703。

  • AD 即内容区域高度,在本例中是 42
  • D 即字体下端(基线之下)高度,为 42*(536/2703) = 8
  • L = 32 – 42 = -10
  • 故,D’ = 8 + -10/2 = 3

即知行内盒的下边缘在基线之下 3px。同时行内盒的高度被视为 32px,故亦知其上边缘在基线之上 29px 处。

我们说啦,整个行盒的高度即 IMG 盒上边缘到 SPAN 盒下边缘。所以得行内盒高度为 90 + 3 = 93px。

1.关键词

关键词出现时不带引号或者尖括号。它们被用作属性值。因为它们不能被替换或者进一步细分,所以它们是终结符。在下面的例子中,thinmediumthick 都是关键词。这意味着它们可以被用作我们 CSS 中的值。

CSS

<line-­width> = <length> | thin | medium | thick

1
<line-­width>  =  <length> | thin | medium | thick

首页index.html

这是项目的入口页面,其实就是一个大容器,在这里加载所有的js和css文件,然后提供一个视图容器就够了,因为从这个页面以后,我们页面就不再会有跳转,全部是通过前端路由来做局部刷新,首页的代码非常精简:

JavaScript

<!doctype html> <html ng-app="QMaker"> <head> <meta charset="utf-8"> <title>Question Maker</title> <link rel="stylesheet" href="/src/lib/bootstrap-3.3.5/css/bootstrap.min.css"> <script src="/src/lib/jquery-1.9.1.min.js"></script> <script src="/src/lib/angular-1.4.1.min.js"></script> <script src="/src/lib/angular-ui-router.min.js"></script> <link rel="stylesheet" href="/src/css/base.css"> <!--{main}--> <script src="/src/js/app.js"></script> <script src="/src/js/controllers.js"></script> <script src="/src/js/directives.js"></script> <script src="/src/js/filters.js"></script> <script src="/src/js/routes.js"></script> <script src="/src/js/services.js"></script> <!--{endmain}--> </head> <body> <div class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <a href="#/" class="navbar-brand">Question Maker</a> </div> </div> </div> <div class="maincontent container-fluid" ui-view> </div> </body> </html>

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
<!doctype html>
<html ng-app="QMaker">
<head>
    <meta charset="utf-8">
    <title>Question Maker</title>
    <link rel="stylesheet" href="/src/lib/bootstrap-3.3.5/css/bootstrap.min.css">
    <script src="/src/lib/jquery-1.9.1.min.js"></script>
    <script src="/src/lib/angular-1.4.1.min.js"></script>
    <script src="/src/lib/angular-ui-router.min.js"></script>
 
    <link rel="stylesheet" href="/src/css/base.css">
    <!--{main}-->
    <script src="/src/js/app.js"></script>
    <script src="/src/js/controllers.js"></script>
    <script src="/src/js/directives.js"></script>
    <script src="/src/js/filters.js"></script>
    <script src="/src/js/routes.js"></script>
    <script src="/src/js/services.js"></script>
    <!--{endmain}-->
</head>
 
<body>
    <div class="navbar navbar-default">
        <div class="container-fluid">
            <div class="navbar-header">
                <a href="#/" class="navbar-brand">Question Maker</a>
            </div>
        </div>
    </div>
    <div class="maincontent container-fluid" ui-view>
 
    </div>
</body>
 
</html>

5 建立行内格式化上下文的块盒的 auto 高度

根据 W3C CSS2.1:10.6.3,该高度是从其上内容边缘到其最后一个行盒的下边缘。只考虑文档流内子盒,绝对定位和浮动子盒应被忽略,相对定位子盒不考虑位移,子盒可以是匿名盒。

在本例中,DIV 盒的行内格式化上下文仅有一个行盒,故其高度取该行盒高度,93px。

1 赞 1 收藏 评论

澳门新葡亰手机版 8

2.基本数据类型

基本数据类型定义核心值,如<length><color>。它们是非终结值因为它们可以被实际的长度值或者颜色值来替换。在下面的例子中,<color>符号是一个基本数据类型。

CSS

<'background-color'> = <color>

1
<'background-color'>  =  <color>

这个<color>在我们的 CSS 中可以被一个真实的颜色值替换,使用一个关键词,一个扩展的关键词,一个 RGB 颜色值,RGBA 值,HSL 或者 HSLA 值,或者 transparent 这个关键词。

CSS

.example { background-color: red; } .example { background-color: honeydew; } .example { background-color: rgb(50%,50%,50%); } .example { background-color: rgba(100%,100%,100%,.5); } .example { background-color: hsl(280,100%,50%); } .example { background-color: hsla(280,100%,50%,0.5); } .example { background-color: transparent; }

1
2
3
4
5
6
7
.example { background-color: red; }
.example { background-color: honeydew; }
.example { background-color: rgb(50%,50%,50%); }
.example { background-color: rgba(100%,100%,100%,.5); }
.example { background-color: hsl(280,100%,50%); }
.example { background-color: hsla(280,100%,50%,0.5); }
.example { background-color: transparent; }

入口文件app.js

有了入口页面,还得有一个js的启动入口,就是这个app.js了,在这里它只做了两件事情:

  1. 启动angular,代码只有一行:

JavaScript

var app = angular.module('QMaker', ['ui.router']);

1
var app = angular.module('QMaker', ['ui.router']);

我们拥有了一个名为app的全局模块。这里把ui.router给注入了,因为我们整个应用都用ui-router来做路由,后面会做详细介绍。

2. 把ui-router的$state和$stateParams服务挂到$rootScope上,这样我们在后面所有的模块中,都能够访问到路由参数,不必在每个地方都注入一次了。代码也是相当简单:

JavaScript

app.run(function($rootScope, $state, $stateParams) { $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; });

1
2
3
4
app.run(function($rootScope, $state, $stateParams) {
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
});

3.属性数据类型

属性数据类型是一个用来定义属性真实值的一个非终结符号。它用尖括号包住属性的名字(使用引号包住)。在下面的例子中,<'border-width'>字符是一个属性数据类型。

CSS

<'border-­width'> = <line-­width>{1,4}

1
<'border-­width'>  =  <line-­width>{1,4}

属性数据类型可能会直接作为属性出现在我们的 CSS 中。在下面的例子中,border-width属性就被用来为.example类名定义一个 2px 的边框。

CSS

.example { border-width: 2px; }

1
.example { border-width: 2px; }

控制器合集controllers.js

controller.js里面是所有的controller定义,由于这个项目比较小,而且反正最后都要合并,所以就都放在一个文件里了,这样可以使用链式写法app.controller(‘a’, …).controller(‘b’, …), 一口气将所有的controller都定义好。如果项目比较大,controller多,可以把controllers建为一个文件夹,然后在里面放各个controller。

controller里面就是跟业务相关的一些代码了,如试题数据的初始化,添加答案、删除选项等操作。

但是当我们需要发起ajax请求的时候,如保存试题,就不宜在controller里面直接写了,这样会造成逻辑混杂代码混乱。所有需要请求服务端的操作,我们可以抽象为一个个服务,进行“分层”,通过ng提供的service机制来做调用。

4.非属性数据类型

非属性数据类型是一个和属性名称不相同的非终结符。然而,它定义了某个属性的各方面。举例来说,<line-width>不是一个属性,但是它是一个定义了各种<border>属性的数据类型。

CSS

<line-­width> = <length> | thin | medium | thick <'border-­width'> = <line-­width>{1,4}

1
2
<line-­width>  =  <length> | thin | medium | thick
<'border-­width'>  =  <line-­width>{1,4}

服务合集services.js

接上面,所有和试题相关的服务端请求,我们可以封装成一个QuestionService,这个服务提供:提交试题、删除试题、更新试题等服务,这样层次就很清晰了。

所以,在services.js中,我们定义所有和服务相关的东西,在本项目中,我们的服务全都是ajax请求,可以用ng提供的$http服务来很方便的完成。事实上service中并不是必须写ajax请求,凡是可以抽象理解为“公共服务”的东西,都可以定义在这里,可以被其他模块随意调用。

组合值选择符

组合值可以通过下面五种方法之一被用到属性值选择符中。

指令合集directives.js

了解过ng的同学应该对指令不会陌生,通过指令我们可以用扩展html标签的方式来很容易的实现一些UI效果,使用方便、可被多个地方公共使用,就像过去我们写jquery插件一样。所有的指令都定义在这个文件中,同样可以使用链式写法,很爽。

在我们的项目中,有一些功能是通用的,例如列表的分页,那么就可以把分页功能做成一个指令。我定义了一个名为pagenav的指令,然后在所有需要用分页的地方就可以调用了,代码如下:

JavaScript

<pagenav pageobj="pageObject" pagefunc="pageFunction"></pagenav>

1
<pagenav pageobj="pageObject" pagefunc="pageFunction"></pagenav>

只需一个标签,然后通过属性指定分页数据和翻页函数即可。

本文由澳门新葡亰手机版发布于web前端,转载请注明出处:理解CSS属性值语法,AngularJs前端架构

上一篇:没有了 下一篇:Web前端框架与类库的思考,用法教程
猜你喜欢
热门排行
精彩图文