前言

老博客的文章搬运。

最近突然想到了这四个概念,然后简单理了一下我认为的他们之间的关系。

Module–模块

模块应该是很基础很简单的一些集合,比如一个页面上的按钮输入框表单下拉菜单等等,这些模块有以下特征:

  • 重要!:不包含特定业务信息,模块是完全通用的;
  • 通常只包含单一功能,如按钮就只提供点击这种操作;
  • 提供基本的属性设置,如class样式data数据等,有的如img组件还会提供srcherf等属性;
  • 提供基本的响应 API 或者 Hooks,因为我们需要让我们的应用知道这个模块现在是什么状态,发生了什么操作,这个很好理解,比如按钮就可以有以下事件:

    1. 鼠标移入事件;
    2. 鼠标按下事件(或手指按下);
    3. 鼠标释放事件(或手指松开);
    4. 鼠标点击事件(手指点击);
    5. 鼠标移出事件。

    这样其他的代码就能对这些事件做出正确的响应。

  • 可选:提供默认的样式。

其实,上面所说的和现在html 中基础元素的特性几乎是一样的,因为我们基本不会使用浏览器默认的样式,以及我们需要一些html中没有定义的控件,如下面这种:

Segmentfault中选择兴趣的模块

这是Segmentfault选择兴趣的一个模块,原生html是不提供这种控件的。它的复杂度很高,但是我们将其分解开便不难发现,已选兴趣中的那些带×的小标签,可以单独实现为一个控件,以及待选中的各项也可以用按钮来代替。从这里可以看出,模块都是可以嵌套的。嵌套后如果不带具体业务信息,它还是一个模块。

Component–组件

组件和模块非常相似,但是,组件和模块有着一个最大的不同:

Component(组件)是具有特定业务属性的 Module(模块)。

如何理解呢?每个组件都会对应着特定的业务:如淘宝网首页中的这个搜索框:

淘宝首页搜索框

其实乍一看,这个搜索框就是由一个输入框模块和一个按钮组件构成的,甚至,你可以用上面描述的Module嵌套法构造一个搜索框模块。但是,当它将各种数据以及事件响应应用到基础模块上时,这就是一个组件。

组件 = 模块 + 业务逻辑

所以,模块我们能在任何页面复用,甚至是”无脑”的复用。但是组件基本只是针对当前业务逻辑(当然其他业务逻辑相同的地方也能复用)。

我为什么要这样理解这两种对象呢?一切都源于以下两个定义:

  1. 组件化(或者说模块化)开发绝不是为了复用,而是为了便于协作开发。
  2. 通过将页面部件进行分块,我们能够在以后的开发中复用以前写好的部件,从而大大加快开发速度。

通过 Module–模块Component–组件 的明确定义,我们轻松达成了上面这两个目标。

Page–页面

有了上面两个定义做基础,Page和理解起来就简单很多了。

Page 其实就是一个单一的页面,页面可以由一个组件构成,也可以由多个组件构成,甚至可以由组件和模块构成(其中的模块,指 滚动到顶部的按钮、酷炫的 Canvas 背景 等这类不具业务信息且也不必添加业务信息的元素)。

同样,作为一个示范,

Facebook个人首页

这是我 Facebook 个人首页的最新动态页面,其中,红框标记的都是组件(还有很多没标出来)。每个组件都对应着特定的业务逻辑(如右侧的好友推荐组件、右下角的聊天组件等),它们共同组成了这个页面,提供了这个页面所具有的一切功能,这样就好理解了。

App–应用

应用由 Page 组成,一个应用中的 Page 数量应该大于或等于一,也就是至少有一个页面。当只有一个页面时(即SPA),所有的组件都挤在一个页面中,通过显示/隐藏的方法 或者 动态加载的办法来变更页面上显示的组件。

一个组件很容易嵌入到另一个组件中,但是一个 App 基本无法嵌入到其他 App 中(除非使用 iframe 这类技术),因为 App 强依赖于当前的 URL 地址,每个 URL 即严格对应着一个 App 状态,也就是说,通过在 Web 浏览器键入某个 URL ,在任何时候我们都能够得到预期中的页面(除去页面自动跳转这种情况)。

总结

以上描述通过以下四个公式来诠释:

Module = 属性 + 事件 + DOM元素

Component = Module * n + 具体业务逻辑

Page = Component n + Module m

App = Page + URL

我用了ModuleComponentPageApp这四个不同的概念将当前的 Web 应用进行了分层分块,极大的方便了自己的开发流程。