`

关于css--的封装、继承、多态

CSS 
阅读更多
第一次听到“CSS模块化”这个词是在WebReBuild的第四届“重构人生”年会上,当时我还想,“哈,CSS也有模块化,我没听错吧?”事实上,我没听错,你也没看错,早就有CSS模块化这个概念了。之所以我把这个拿出来讨论,是因为最近艾维的一个算是比较大的项目——聪明的油出现了一些重构上的危机,因此引发了我们对页面重构中的CSS进行模块化的思考。

首先,什么是CSS模块化?在谈CSS模块化之前我们先看一下百度百科对模块化的解释:

“模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程。每个模块完成一个特定的子功能,所有的模块按某种方法组装起来,成为一个整体,完成整个系统所要求的功能。在系统的结构中,模块是可组合、分解和更换的单元。”

我对上面一段话的理解是,模块化就像我们玩乐高积木一样,一个积木就是一个单元,可以通过组合不同的积木来搭建一个玩具模型。对于一个玩具模型,也可以更换部分积木而迅速变成另一个模型。而CSS模块化的关键,就是如何合适地构建这些单元,也就是一个一个的class,以及如何灵活运用这些单元来达到我们所要的呈现效果。

说了一堆繁杂的话,连我自己都觉得乏味。作为一个热爱编程的页面仔,我想借用面向对象的三大特性来说明CSS模块化——封装、继承、多态。

一、 封装



HTML代码
<div class=”module-a”>
  <h3>标题1</h3>
  <p>描述文字</p>
</div>
<div class=”module-b”>
  <h3>标题2</h3>
  <ul>
    <li>列表</li>
    <li>列表</li>
    <li>列表</li>
  </ul>
</div>

CSS代码
.module-a{.....}
.module-a h3{.....}
.module-a p{.....}
.module-b{.....}
.module-b h3{.....}
.module-b ul{.....}
.module-b ul li{.....}
.module-b ul li{.....}
.module-b ul li{.....}

封装是实现CSS模块化的最基本要求,封装成的各个单元就是基本的CSS模块,可灵活用于组建页面的各种显示样式。

二、 继承


HTML代码
<div class=” module module-A module-A-a”></div>
<div class=” module module-A module-A-b”></div>

CSS代码
.module {.....}
    .module-A {.....}
        .module-A-a {.....}
        .module-A-b {.....}
    .module-B {.....}
        .module-B-a {.....}
        .module-B-b {.....}

继承可谓是CSS模块化的关键所在,由于html元素可以拥有多个类,而且根据优先级,后面定义的属性可以覆盖前面的,正因为这样,继承这个特性发挥了巨大的作用。对于某些多数样式属性相同,仅有几个不同样式属性的定义,可以用这个方法来实现。也可以在不改变某个通用样式类的同时,用HTML调用复合类,突出局部特例。

三、 多态


HTML代码
<div class=”module-A”></div>
<div class=”part-A ”>
    <div class=”module-A”></div>
</div>
<div class=”part-B ”>
    <div class=”module-A”></div>
</div>
<div class=”part-C ”>
    <div class=”module-A”></div>
</div>

CSS代码
.module-A {.....}
.part-A .module-A {.....}
.part-B .module-A {.....}
.part-C .module-A {.....}

多态主要用于同一模块在页面的不同部分或者不同页面之间呈现出不同的样式。对于CSS的多态,一个很经典而且常用的例子就是导航栏。我们知道,导航栏往往需要标识出当前页面所在的导航链接。也就是说,对于导航栏的链接,通常有两种形态,一种是常态,一种是高亮态,比如处于主页时,主页的链接就是高亮态的,其他导航链接是常态的。这个时候,很多人喜欢在li上加上一个current类,用来把该导航链接设置为高亮态,但是我觉得这种方式并不理想。

为什么呢?因为对于结构一样的导航栏,后台人员在处理时,往往是抽出成一个公共结构,然后各个页面都引入这个结构。这对于后期的维护是相当有效的,因为涉及导航栏的修改仅需修改一次即可,如果不这么做,那么修改的次数将会等于页面的个数,而且容易出错。对于这种情况,多态就可以很好地解决,因为我们可以在每个页面的body(或者其他地方)加上一个类来标识不同的页面(此类可以不定义任何样式)。那么,根据多态的特性,我们就可以为不同页面的导航设置不同的形态,同时又保持了导航链接的结构一致性。举例如下:

HTML代码
主页:
<body class=”index”>
  <ul class=”nav”>
    <li class=”index”><a href=”#”>主页</a></li>
    <li class=”page1”><a href=”#”>内页1</a></li>
    <li class=”page2”><a href=”#”>内页2</a></li>
  </ul>
</body>
内页1:
<body class=”page1”>
  <ul class=”nav”>
    <li class=”index”><a href=”#”>主页</a></li>
    <li class=”page1”><a href=”#”>内页1</a></li>
    <li class=”page2”><a href=”#”>内页2</a></li>
  </ul>
</body>

CSS代码
//定义常态
.nav{.....}
.nav .index{.....}
.nav .page1{.....}
.nav .page2{.....}
//定义高亮态
.index .nav .index{.....}
.page1 .nav .page1{.....}
.page2 .nav .page2{.....}

这个就是多态的经典应用之一。

————————————补充部分————————————
joe哥指正,以上的这种对导航的处理办法不太好,因为导航是一个公用组件,所谓公用,就是应该结构和样式都是公用的,上面的那种方法没有做到样式上公用,因为很明显定义高亮态那里需要用到其他页面的样式类,而且joe哥提到可移植性的问题,如果这个导航搬到其他地方,那么就需要为新的页面的body全部都添加一个类(这个我真没想过导航还可以给多个网站重用,我眼光太短浅了)。那么,究竟什么做才是比较主流的呢?加current,没错,就是加 current,这个被我一开始就否决的方法。那么又回到原来的问题,既然我们是引入同一个导航文件,那么current能加到哪里呢?joe哥提出一个被我们都忽略了的方法,脚本!可以是js,可以是php,原来我们可以动态添加current类到导航去,惊讶吧!

好吧,我承认我有点过于兴奋了,大伙儿看例子吧~

HTML代码
<ul class=”nav”>
  <li class=”index” id="index"><a href=”#”>主页</a></li>
  <li class=”page1” id="page1"><a href=”#”>内页1</a></li>
  <li class=”page2” id="page2"><a href=”#”>内页2</a></li>
</ul>

CSS代码
//定义导航的样式
.nav{.....}
.nav li.index{.....}
.nav li.page1{.....}
.nav li.page2{.....}
//定义高亮态
.nav li.current{.....}

JS代码
function addCurrent(class,html_id){
  //class为增加的样式类名,html_id为需要增加样式类的html元素的id
  document.getElementById(html_id).addClass(class); //这里的class就是‘current’,addClass方法的实现我这里就不多说了,你可以用jquery或者别的,甚至自己写
}

这种做法对于不同的页面,或者新增的页面,只需改js的一个参数即可,做到了把导航部分真正实现模块化、组件化,公用的部分就应该公用到底,不留一点余地。不过我还想说一点是,如果你的current(高亮态)不是单独的换个背景颜色之类的,而是用雪碧图这类的方法,每个导航链接的current类都是不同的,那么以上的这种方法,貌似还有待改进。
————————————补充部分结束————————————

事实上应该指出,我这里讨论的只是CSS模块化的一部分,可以说是比较微观的一部分。还有一些对CSS进行比较宏观地划分模块的说法,比如按页面来划分,一个页面或者说一个区域为一个模块,比如像“幸福收藏夹”上所说的划分方法:

“聪明的油”网站的划分标准更大一些,是以网站的专题为模块,不幸的是,很多专题的页面风格都是类似的,导致各个模块间存在大量的冗余代码,这意味着对样式的改动将会相当麻烦,一个地方的改动需要同时修改多个css文件。

表面上看,虽然对CSS模块划分得细是一个不错的想法,但并不是越细越好。现在的一些开源系统,如dedecms,甚至说YUI框架的1.0版本,都流行一种做法,就是把CSS模块细分成单属性,比如把宽度960px定义为.w960,把清除浮动定义.clear,把字体绿色定义为.green等等。

这样做的好处是可以对页面元素的样式进行快速组装,通过引入多个类便可以达到我们想要的效果。但是,这样的做法会导致另外一个问题。大家想,这么做与内联样式有什么区别?如果有一天,我们想要把多个地方的字体颜色由绿色改为红色,那么我们要做的不是改动css的color属性,而是把这些html元素的class都由green改为red。请注意,我们的初衷是改变的页面表现,但最终我们需要改变结构来达到我们的目的,这样就做不到结构与表现的分离了。

究竟怎么样划分CSS模块,又怎么来用这些模块来组建页面元素才是合适,其实很难找到一个标准,这不仅需要结合具体的页面要求,还需要一定的经验。

以上纯属个人见解,如有错误,欢迎指正。
分享到:
评论

相关推荐

    前端模块化脚手架,可实现类似java的封装继承多态特性

    这个名为“前端模块化脚手架”的工具,旨在为前端开发者提供一个类似于Java语言的封装、继承和多态特性的开发环境。通过这样的框架,开发者可以在JavaScript中模拟出面向对象编程的特性,使前端开发更加规范和高效。...

    JavaScript使用prototype原型实现的封装继承多态示例

    最后,通过在线HTML/CSS/JavaScript代码运行工具,可以进一步测试代码的运行结果,验证封装、继承和多态是否按预期工作。如果遇到任何问题,可以参考《javascript面向对象入门教程》、《JavaScript错误与调试技巧...

    Java零基础-面向对象封装性.md

    在Java语言中,面向对象编程(OOP)是其核心特性之一,而封装性则是面向对象编程四大特性(封装、继承、多态、抽象)的基础。封装性主要指的是隐藏对象的属性和实现细节,并对外提供一组访问和操作这些属性的方法。...

    基于JDK接口、多态、继承、封装与反射的Java编程学习源码

    该项目是一个专注于Java编程基础学习的源码集,涵盖JDK接口、多态、继承、封装与反射等核心概念。源码集包含43个文件,其中Java源文件22个,CSS样式文件7个,以及HTML、下载链接、文档和其他辅助文件。通过这个源码...

    js-html-css-boolzap

    2. **面向对象编程**:类、构造函数、原型链、继承、封装和多态。 3. **ES6新特性**:箭头函数、模板字符串、let和const、解构赋值、Promise、async/await等。 4. **DOM操作**:如何通过JavaScript操作HTML元素,...

    js-Prototype.rar

    JavaScript中的原型(Prototype...这些HTML文件可能详细解释了JavaScript的原型、封装性、多态、继承和私有属性等概念,通过阅读和学习这些文件,开发者可以深入理解JavaScript的面向对象编程特性,并提升其编程能力。

    Auntion TableSort(最新修改,支持Float,支持锁定不排序行)

    封装,继承,多态. 继承请使用prototype ----------------------------------------------------------------------------- &gt;对于新手: 如何使用? 请参看 使用实例_1.htm : ■ 建立一个table ■ 如需美化...

    html,css,java,java框架帮助文档

    - 继承、封装和多态:面向对象三大特性,继承允许子类继承父类的属性和方法,封装隐藏实现细节,多态允许同一接口有多种实现。 - 控制流:如条件语句(`if`、`switch`)、循环(`for`、`while`、`do-while`)。 -...

    javaOO总结(DIV+CSS浏览器兼容方法的总结)

    标题中的“JavaOO”指的是Java面向对象编程,这是Java编程的核心概念,主要涉及类、对象、封装、继承、多态等关键知识点。面向对象编程允许我们以更接近现实世界的方式组织代码,提高代码的可读性和可维护性。在Java...

    JS,CSS 以及浏览器

    3. **面向对象**:类、构造函数、原型链、继承、封装、多态。 4. **异步编程**:事件循环、回调函数、Promise、async/await、Generator。 5. **DOM操作**:获取元素、修改元素属性、添加删除元素、事件处理。 6. **...

    css html css js Ajax java sql 菜鸟教程离线版 等帮助文档大全.rar chm文件

    - 类、对象、封装、继承和多态是Java的面向对象特性。 - JSP (JavaServer Pages)是Java的动态网页技术,结合HTML模板和Java代码。 7. **SQL (Structured Query Language)** - SQL是用于管理和处理关系型数据库的...

    java & web 面试题

    首先,Java 作为面向对象的编程语言,其基础包括类、对象、封装、继承和多态等基本概念。理解这些概念对于编写可维护、可扩展的代码至关重要。面试中,可能会问到如下的问题: 1. **Java 类与对象的区别是什么?** ...

    css+html+java 中英文帮助文档

    2. 继承与多态:继承使子类能共享父类的属性和方法,多态允许不同的子类对象对同一消息作出不同的响应。 3. 封装:隐藏实现细节,仅通过公共接口与外界交互,提高代码的重用性和安全性。 4. 接口与抽象类:接口...

    Java参考文档

    - **封装、继承和多态**:面向对象的三大特性,封装提供数据保护,继承实现代码复用,多态增加程序灵活性。 - **异常处理**:Java中的try-catch-finally语句块用于捕获和处理运行时错误。 - **集合框架**:包括...

    面向对象与交互式程序设计.pdf

    - 面向对象的概念包括封装、继承和多态。 - 封装隐藏了对象的内部状态,只暴露有限的操作接口。 - 继承允许创建类的层次结构,子类可以继承父类的属性和方法。 - 多态允许使用父类型引用子类型对象,提供了方法...

    Java工程师面试集

    - **封装、继承和多态**:这是面向对象编程的三大特性,封装保护数据,继承实现代码复用,多态提高程序灵活性。 - **异常处理**:了解如何使用try-catch-finally结构处理运行时错误,并熟悉各种预定义异常类型。 ...

    1.JavaScript面试真题-210页.zip

    - 面向对象设计原则(封装、继承、多态) 3. **TypeScript** - 类型系统(基本类型、联合类型、接口、泛型) - 类与继承(与JavaScript的区别与联系) - 装饰器(用于元编程,修饰类、属性、方法) - 编译选项...

    java1000题基础百战程序员

    - 面向对象的基本概念:封装、继承、多态 - 类与对象 - 构造方法与析构方法 - 继承与抽象类 - 接口与实现 - **异常机制** - 异常处理的重要性 - try-catch-finally结构 - 自定义异常 - 检查性异常与运行时...

    JavaSE html+CSS基础笔记归纳.zip

    在Java面试中,通常会涉及面向对象编程概念(如封装、继承、多态),集合框架(List、Set、Map接口及其实现类),异常处理,IO流,线程同步,JVM内存模型,设计模式,Spring框架等知识点。面试题可能包括编程题,也...

    上海lamp兄弟连 css课件

    8. **面向对象编程**:类、对象、继承、封装、多态等概念。 9. **PHP框架**:可能会介绍Laravel、Yii、Symfony等流行的PHP框架,它们提供了快速开发和良好的结构。 【LAMP架构】 LAMP是Linux(操作系统)、Apache...

Global site tag (gtag.js) - Google Analytics