一. 前言
          最开始刚接触前端时,感觉所有的操作都是在 control+c 和 control+v,对于编写html页面来讲,每个页面大部分的结构都是相似的;对于写css样式,很多时候都是大段大段的粘贴,比如按钮的hover效果,也许只是背景颜色不同,box-shadow都是一样的,而box-shadow却需要带上各种浏览器前缀。Sass 的出现,带来了强大的 @mixin 和 @include,而且缩进语法也让页面清爽了不少,不用再看一大长串的样式了;compass 自带的自动添加浏览器前缀告别了手动粘贴;自动生成的雪碧图,告别了PS自己拼图的境地。对于 html页面的编写,现在使用 jade,同样提供了引入和大量减少手敲字符的劳动量。



二. 前端基本结构
          现在的趋势是前段工程模块化,简而言之就是前端页面是一个由『积木』(组件)搭建起来的『楼房』(完整html页面)。
          这样做的好处主要有两点:
               1. 组件可以在不同项目中复用,最大的改动可能只是『换肤』(修改css文件)。
               2. 如果你的项目使用了WebApi,那么这样的组件式开发将完美契合你的开发,也就是说一个组件是一个VM(或者是C)。
          那么,我们的一个组件需要包含什么呢?需要包括:结构(html)、行为(js)、样式(css)、数据绑定(ag、react等)。
         
          其中,html(jade)主要控制组件结构;js文件控制组件动画等;css(sass)让组件变『漂亮』,并且有的组件需要做到响应式的显示;vm则将数据绑定到组件上。
          这样,我们的整个项目就是这样的:       
层级结构
解释
一个项目
由许多的页面组成。
一个页面
由许多组件填充
有时也会出现组件套这组件的情况,比如一个模态窗里边套着另一个组件等情况
其中,页面的css只是控制组件的位置和大小
对于大型团队,组件可以分配给不同的人去编写,因为组件之间耦合程度很低

一个组件包含
结构:html
样式:css
行为:js
数据:vm
         

 
三.  模块化开发技术
          这一部分主要介绍一下之前提到的jade和sass如何配合模块化开发。
     A. HTML编写新方式——Jade
          如果你因为 html 的各种『 < 』和『 /> 』而烦恼,那么推荐使用 jade(http://naltatis.github.com/jade-syntax-docs) 。这里只是简要的说如何使用 Jade中的技术 来配合上面说的开发方式。
          根据刚才的开发模式,观察上面的组建类型,不难发现组件分为两种形式。一种是『盒子』,另一种是『零件』。
               盒子就是指该组件只是一个容器,如模态窗、滑动的一个抽屉。大部分盒子都不会有数据绑定的任务,相反,它的行为 js 可能会比较多,即它可能会包含很多的动画。
               因为盒子『可能它的内部需要包含其他组件』的特性,我们就不能只用 Jade 提供的 include 来简单引入组件,就需要使用 mixin 来实现。
mixin SlideBox(name)
    div(data-who="#{name}")
        //盒子内容
        div
            block
        a
              
               如上图,我们定义了一个叫 SlideBox 的『盒子』,引用他可以传入一个叫 name 的参数,并且它拥有一个装东西的 block ,它代表这个盒子可以装的东西。这样定义之后我们就可以在主页面去引用它了,如下图:
include Components/m-SlideBox_m/SlideBox
+SlideBox("test")
    include Components/CwList_r/CwList

               首先我们先将 mixin 引入进来,并且使用 +Name来引入这个『盒子』,并且下一行缩进后将需要添加的『零件』放到这个『盒子』里。这样,它就会生成如下图的html片段了。
<!-- 收缩展开盒子Created by Jason on 15/12/14.-->
<div data-who="test">
    <!--盒子内容-->
    <div>
        <!-- 课件列表Created by Jason on 15/12/14.-->
        <div ms-controller="CwList">
            <a ms-repeat="list"><!--图-->
                <div><img ms-attr-src="el.img"/></div>
                <!--文字-->
                <div><span>{{el.name}}</span><span>评论数{{el.contNum}}</span></div>
            </a>
        </div>
    </div>
    <a></a>
</div>

               有的情景下,我们的『盒子』需要变成一个『柜子』,就是说需要多个地方去装我们的『零件』,那我们定义『盒子』时,只需要加入多个 block 就可以了,如下图
mixin SlideBox(name)
    div(data-who="#{name}")
        //盒子内容
        div
            block
        a
            block

include Components/m-SlideBox_m/SlideBox
+SlideBox("test")
    include Components/CwList_r/CwList
    include Components/CommentBox_r/CommentBox

          这样我们的盒子开发基本就结束了。
          对于零件,我们经过实践发现也会分为以下两种:
               1. 零件中不包含任何可变样式或属性,或者虽然零件样式相同,但是对应的WebAPI是两个。这样的情况不包含可以使用 媒体查询 或 JS 控制样式的情况。
               2. 固定样式的零件,比如搜索框、导航Nav等零件。
         
          对于可变零件的编写,依然使用 mixin 来实现,比如下边的一个零件
mixin CwList(Type,controller)
    link(rel="stylesheet" href="../Components/m-CwList_r/CwList.css")
    div(ms-controller="#{controller}" class="#{Type} hex-cmpnt-CwList")
        a(ms-repeat="list").one
            //图
            div.img
                img(ms-attr-src="el.img")
            //文字
            div.info
                span.title {{el.name}}
                span.com 评论数{{el.contNum}}
          这个零件中,包括了两个变量 Typecontroller
          这个零件的结构对应两种样式,一种是横向列表,另一种是大图列表。因此这个零件将有两种样式名;同时零件也对应两个不同的 WebAPI。
          因此,需要实现这个零件就需要使用 mixin

          对于固定样式的零件,那么就简单的使用 include 来引入就可以了。如下图的搜索框组件:
link(rel="stylesheet" href="../Components/Search_r/Search.css")
div.hex-cmpnt-Search
    i
    input(type="text" placeholder="请输入关键字")

     B. Css编写——Sass
          我们这样的开发模式,要达到的目的就是提高代码的复用率,那么我们在开发的时候就需要考虑到之后的项目可能会改变的部分。
          对于 Css 文件,问题就是不同项目主色调可能不同,那么我们就需要将样式中所有的背景、文字和阴影颜色,图片引用以及可能变化的宽度或高度提取出来,通过引用不同的变量组文件,达到组件复用。目录结构如下图:
          可以看到,对于一个组件Sass文件,可能对应多个变量组(即两种配色方式)。
          我们先来看一下其中一个皮肤文件:
// -----------------------------   上一页&下一页   -----------------------------
// ============================== 变量 ==============================
$BeforANext_height44px
$BeforANext_background_color#ffffff
$BeforANext_border_color#d5d5d5
$BeforANext_back_border_color#d5d5d5
$BeforANext_back_image"return"
$BeforANext_before_border_color#d5d5d5
$BeforANext_before_image"before"
$BeforANext_next_image"next"
          这个方式用到了 Sass 中的变量声明方式  $Name 。这样的变量包括组件的各种颜色、引用的图片名称和组件的宽高等参数,这样就构成了一个『皮肤』文件。
          那么我们在主 Sass 引用中引用如下图:
// ============================== 变量 ==============================
@import "constant_1"
// ============================== 样式 ==============================
.hex-cmpnt-BeforANext
  height$BeforANext_height
  width100%
  border-bottom1px solid $BeforANext_border_color
  background-color$BeforANext_background_color
 div
    display: block
    &.back
      float: left
      margin8px 0 0 20px
      > a
        display: block
        height27px
        width27px
        border-radius50%
        border1px solid $BeforANext_back_border_color
        @include images-sprite($BeforANext_back_image)
          我们这个主Sass文件,使用的是第一个皮肤,因为我们的名称定义已经固定,所以对于主Sass来说,我们只需要引用变量名称,为不需要考虑它的值到底是什么。
          这样,我们的零件可已拥有多个皮肤,分别在不同的项目中使用。