一、什么是MVC

(一)MVC包括三部分,即M、V、C。

1、M:模型model用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法,会有一个或多个视图监听此模型。一旦模型的数据发生变化,模型将通知有关的视图。
2、V:视图view是它在屏幕上的表示,描绘的是model的当前状态。当模型的数据发生变化,视图相应地得到刷新自己的机会。
3、C:控制器controller定义用户界面对用户输入的响应方式,起到不同层面间的组织作用,用于控制应用程序的流程,它处理用户的行为和数据model上的改变。

  1. import $ from 'jquery'
  2. const m = {
  3. data : {
  4. n : xxx
  5. }
  6. }
  7. const v = {
  8. init(){
  9. $('body').innerHTML = `<div>初始化n的值</div>` // 初始化HTML
  10. },
  11. render(){
  12. $('body').innerHTML = `<div>更新n的值</div>` // 更新HTML
  13. }
  14. const c = {
  15. init(){
  16. v.init()
  17. this.events()
  18. },
  19. events(){
  20. $('div').on('click', function(){
  21. console.log('在这修改n的值') // 修改n的值
  22. render()
  23. })
  24. }
  25. }

(二)M、V、C之间的联系

一千个程序员心里有一千种MVC,每个人讲的MVC都不尽相同,以下是我理解的MVC之间的关系。
当用户与view进行交互的时候,会触发view的一些事件,这些事件会被controller模块监听到,controller会根据不同的用户事件去调用model层的一些接口,通过这些接口修改model层的数据。
在之前view会通过观察者模式去观察model层的数据,如果当model层的数据改变的时候,则会通过事件通知的方式通知view层,最后view再根据新的数据改变自己的状态,也就是改变用户界面。
MVC.png

二、eventBus

eventBus主要用于对象间通信,eventBus允许我们在一个对象中发出一个事件,而在另一个对象中侦听该事件。eventBus 提供了 on、off 和 trigger 等 API,可以使用 on 监听事件,trigger 触发事件。使用 eventBus 可以满足最小知识原则,m 和 v 互相不知道对方的细节,但是却可以调用对方的功能。

  1. import $ from 'jquery'
  2. const eventBus = $({})
  3. const m = {
  4. data : {
  5. n : xxx
  6. },
  7. update(data){
  8. Object.assign(m.data, data)
  9. eventBus.trigger('m updated') // 触发'm updated'
  10. }
  11. }
  12. const v = {
  13. init(){},
  14. render(){}
  15. }
  16. const c = {
  17. init(){
  18. v.init()
  19. eventBus.on('m updated', () => { // 监听'm updated'
  20. v.render(m.data.n)
  21. })
  22. },
  23. events(){
  24. $('div').on('click', function(){
  25. m.update('更新n')
  26. })
  27. }
  28. }

三、表驱动编程

表驱动方法(Table-Driven Approach)是一种使你可以在表中查找信息,而不必用很多的逻辑语句(if或case)来把它们找出来的方法。事实上,任何信息都可以通过表来挑选。在简单的情况下,逻辑语句往往更简单而且更直接。
简单讲是指用查表的方法获取值。

  1. if (key = "Key A"){
  2. 处理 Key A 相关的数据和行为。
  3. }else if (key = "Key B"){
  4. 处理 Key B 相关的数据和行为。
  5. }else if ... // 以此类推,处理C D E F...

上述代码可以改装成:

  1. let hashTable = {
  2. A: {
  3. data: "数据1",
  4. action: "行为1"
  5. },
  6. B: {
  7. data: "数据2",
  8. action: "行为2"
  9. }
  10. C:...
  11. D:...
  12. ...
  13. }
  14. function handleTable(key) {
  15. return hashTable[key]
  16. }
  17. console.log(handleTable('A').data)

如果继续增加C D E F … if…else…方式需要对每个数据都要单独写一句,而使用表驱动编程只需要把新的数据和行为添加到表中即可,代码复杂度更稳定。

四、模块化

(一)什么是模块

  • 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
  • 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信

    (二)模块化

    如此把各个文件封装成一个模块,只暴露一个对外的接口,HTML文件只需要导入main.js一个文件即可,不需要知道每个模块内部的细节。如下,MVC只暴露cantroller模块一个接口即可。
    1. //app1.js
    2. import './app1.css'
    3. import $ from 'jquery'
    4. const m = {data : {}}
    5. const v = {init(){}, render(){}}
    6. const c = {
    7. init(){
    8. v.init()
    9. this.events()
    10. },
    11. events(){
    12. 更新data
    13. render()
    14. }
    15. }
    16. export default c
    1. //main.js
    2. import app1 from './app1.js'
    1. <script src='mian.js'></script>

(三)模块化的好处

  • 避免命名冲突(减少命名空间污染)
  • 更好的分离, 按需加载
  • 更高复用性
  • 高可维护性
  • 符合知识最小化原则(使用的人知道的越少越好)