如果要说我目前在入门阶段遇到的几个让我最没自信的家伙,一个要数算法,然后就是 MVC 了。所以今天就简单写一下自己的一些思考。
可以先看一下 这篇文章
为什么要有设计模式?
Dry 原则:Don't Repeat Yourself
- 代码级别的重复(相同的三行代码写了两遍)
- 页面级别(类似的页面做了十遍)
- 所有的页面都可以使用 MVC 来优化代码结构(万金油)
抽象思维
- 最小知识原则
- 引入一个模块需要 html css js
- 引入一个模块需要 html js
- 引入一个模块需要 js
- 需要知道的知识越来越好,模块化为这一点奠定了基础
- 代价:会让页面最开始是空白的,没有内容和样式
- loading 图片、骨架、占位内容、SSR 技术(服务器端渲染)
- 以不变应万变
- 每一个模块都可以用 M + V + C 搞定,但有时候会多余一些用不到的代码,有时候遇到特殊情况不知道怎么变通
- 表驱动编程
- 当看到大批类似但不重复的代码,眯起眼睛,看哪些数据才是重要的
- 把重要的数据做成哈希表,代码会变简单
- 事不过三
- 同样的代码写了三遍,就抽象成函数
- 同样属性写了三遍,就做成共用属性(原型或类)
- 同样的原型写了三遍,就应该用继承
- 俯瞰全局
- eventBus
- view = render(data)
- 比起操作 DOM 对象,直接 render 简单多了,只要改变 data,就可以得到对应的 view
- 数据永远从 JS(数据)流向页面(视图)
- 代价:浪费性能
- 虚拟 DOM 让 render 只更新该更新的地方
- 解耦
MVC
MVC 是一种有名的设计模式,我们可以把一个模块用三个对象表示出来,这三个对象就是 M、V 和 C:
M - Model,数据模型,负责操作所有数据
V - View,视图,负责所有 UI 界面
C - Controller,控制器,负责其他
Model
我们可以用伪代码来尝试表示 Model 对象:
|
|
他是一个专门用来存放数据的对象,并且可以提供一系列对数据进行操纵的 API,比如 Create、Remove、Update、Get 等。
View
同样的,我们可以来表示一下 View 对象:
|
|
我们可以在 View 指定一个元素 element,可以对他内部的 HTML 代码进行修改和重载,同时也可以对其内部的元素进行增删改查等操作。
Control
对于 Control 部分的伪代码,我们也许可以这样写:
|
|
在 Control 中,我们可以完成初始化操作,可以为元素绑定事件,并书写事件方法,用来触发 M 或 V 的更改。
当然,对 MVC 的理解不同的人可能有不同的想法,作为初学者我只是简单理解了一下。比如有时候,我们对 C 的界定可能并不是那么明显——它既可以操作视图,又可以操作数据,那么为什么不把他就放在 V 或者 M 中呢?
EventBus
个人认为 EventBus 的出现主要是由于模块化和 MVC 的推进。前文也说了,在一个模块中,我们可以把所有的东西都分成 M V C 这三个对象来表示,这样虽然我们可以用统一形式的代码来表示几乎所有的情况,但同时也会带来一些问题。
首先,我们可以看看我们原来修改元素内容的方式:
|
|
是一个非常自然的线性关系,当事件被触发时,直接修改 DOM 来改变元素内容,DOM 操作和数据是混在一起的,我们并没有在代码中单独保存数据。
而使用 MVC 之后,我们修改元素内容的方式变成了:
|
|
看起来稍稍有些复杂:
当事件被触发之后,C 中的事件绑定函数会调用 M.Update 方法来操纵 data,
但是负责视图的 V 此时并不知道事件已经触发,因此我们需要借助一个 “事件总线 EventBus” 来帮助我们完成事件从 M -> V 传递的这样一个过程,
M 更新完 data 之后触发 eventBus,
V 监听 eventBus,知道 M 已经更新完 data 了,然后调用 V.Render 方法更新视图。
当然除了帮助在 M V C 三个对象之间传递事件以外,eventBus 还可以帮助在模块之间传递事件。
下面用伪代码给出了一个 EventBus 常用 API 示例:
|
|
表驱动编程
表驱动法,又称之为表驱动、表驱动方法。 “表”是几乎所有数据结构课本都要讨论的非常有用的数据结构。表驱动方法出于特定的目的来使用表,程序员们经常谈到“表驱动”方法,但是课本中却从未提到过什么是"表驱动"方法。表驱动方法是一种使你可以在表中查找信息,而不必用很多的逻辑语句( if 或 case )来把它们找出来的方法。事实上,任何信息都可以通过表来挑选。在简单的情况下,逻辑语句往往更简单而且更直接。但随着逻辑链的复杂,表就变得越来越富有吸引力了。
还是用伪代码来表示一下,
|
|
模块化
我对模块化的理解其实很简单:
首先,模块化可以把不同的功能分成不同的模块,模块之间的瓜葛要尽可能小,最好每个模块在不知道外部情况的时候也可以正常工作,这样我们之后维护代码只需要关注特定模块的部分即可;
其次,我们可以将 M V C 抽象为三个模块,做成 M 模块、V 模块、C 模块,这三个模块不需要关注具体的细节,只需要实现对应基本的、通用的功能,然后把 M V C 和每一个实现具体功能、操纵具体元素的模块分开,这样如果我们要对 M V C 进行统一的修改,就不需要深入每一个具体功能之中了。