浅析 MVC

180 阅读4分钟

  • MVC 三个对象分别做什么

MVC是三个单词的首字母缩写,它们是Model(模型)、View(视图)和Controller(控制)。

这个模式认为,程序从结构上看,都可以分成三层。

  • 最上面的一层,是直接面向最终用户的"视图层"(View)。它是提供给用户的操作界面,是程序的外壳。
  • 最底下的一层,是核心的"数据层"(Model),也就是程序需要操作的数据或信息。
  • 中间的一层,就是"控制层"(Controller),它负责根据用户从"视图层"输入的指令,选取"数据层"中的数据,然后对其进行相应的操作,产生最终结果。

这三层是紧密联系在一起的,但又是互相独立的,每一层内部的变化不影响其他层。每一层都对外提供接口(Interface),供上面一层调用。这样一来,软件就可以实现模块化,修改外观或者变更数据都不用修改其他层,大大方便了维护和升级。

  • EventBus 是做什么用的?

Eventbus(事件总线)是个很聪明的想法,他解决了事件之间互相通信的问题,就像是所有组件共用相同的事件中心,因为刚接触,所以先举一个用jQuery简单实现的例子。

假设我们想实现 a b 两点之间的通讯,当a点触发特定事件时,b点能够检测到。

const eventBus = $(window)  //先声明一个eventbus

  update(data) {     //当A点每次触发update方法,eventbus都会被触发
    Object.assign(m.data, data)
    eventBus.trigger('m:updated')
    localStorage.setItem('n', m.data.n)
  },

  init(container) {
    v.init(container)
    v.render(m.data.n) // view = render(data)
    c.autoBindEvents()
    eventBus.on('m:updated', () => {          //使用eventBus.on方法来监听A处触发的事件,每当触发一次即可执行回调函数
      console.log('here')
      v.render(m.data.n)
    })
  }

  • 表驱动编程

表驱动法是一种编程模式(scheme)——从表里面查找信息而不使用逻辑语句(if和case)。事实上,凡是能通过逻辑语句来选择的事物,都可以通过查表来选择。对简单的情况而言,使用逻辑语句更为容易和直白。但随着逻辑链的越来越发杂,查表法也就愈发显得更具吸引力。

例如:if-else

function translate(term) {
    if (term === '1') {
        return '一'
    } else if (term === '2') {
        return '二'
    } else if (term === '3') {
        return '三'
    } else {
        return '???'  
    }
}

// 如果想添加一个新的名词翻译,需要再添加一个if-else逻辑,例如:
function translate(term) {
    if (term === '1') {
        return '一'
    } else if (term === '2') {
        return '二'
    } else if (term === '3') {
        return '三'
    } else if (term === '4') {   
        // 此处添加了一个新的名词翻译
        return '四'
    } else {
        return '???'  
    }
}

表驱动:

function translate(term) {
    let terms = {
        '1': '一',
        '2': '二',
        '3': '三'
    }
    return terms[term];
}

// 如果想添加一个新的名词翻译,只需要在terms中添加一个新的表项,不需要修改整个逻辑
function translate(term) {
    let terms = {
        '1': '一',
        '2': '二',
        '3': '三'
        '4': '四'   // 添加一个新的名词翻译
    }
    return terms[term];
}

  • 模块化概念

模块是一种将 JavaScript 程序拆分为可按需导入的单独模块的机制,

  • 导出模块的功能

最简单的方法是把它(指上面的export语句)放到你想要导出的项前面,比如:

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return {
    length: length,
    x: x,
    y: y,
    color: color
  };
}

你能够导出函数,var,let,const, 和等会会看到的类。export要放在最外层;比如你不能够在函数内使用export

一个更方便的方法导出所有你想要导出的模块的方法是在模块文件的末尾使用一个export 语句, 语句是用花括号括起来的用逗号分割的列表。比如:

export { name, draw, reportArea, reportPerimeter };

还有一种导出类型叫做 default export —这样可以很容易地使模块提供默认功能,

export default randomSquare;  //注意,不要大括号。

每个模块只允许有一个默认导出, 我们知道 randomSquare 就是需要的那个。上面的那一行相当于下面的缩写:

import {default as randomSquare} from './modules/square.mjs';
  • 导入功能到你的脚本

你想在模块外面使用一些功能,那你就需要导入他们才能使用。最简单的就像下面这样的:

import { name, draw, reportArea, reportPerimeter } from '/js-examples/modules/basic-modules/modules/square.mjs';

使用 [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) 语句,然后你被花括号包围的用逗号分隔的你想导入的功能列表,然后是关键字from,然后是模块文件的路径。模块文件的路径是相对于站点根目录的相对路径,对于我们的basic-modules 应该是 /js-examples/modules/basic-modules

  • 应用模块到你的HTML

现在我们只需要将main.mjs模块应用到我们的HTML页面。 这与我们将常规脚本应用于页面的方式非常相似,但有一些显着的差异。

首先,你需要把 type="module" 放到 <script> 标签中, 来声明这个脚本是一个模块:

<script type="module" src="main.mjs"></script>

你只能在模块内部使用 importexport 语句 ;不是普通脚本文件。

  • 动态加载模块

这个新功能允许您将import()作为函数调用,将其作为参数传递给模块的路径。 它返回一个 promise,它用一个模块对象来实现(参见Creating a module object),让你可以访问该对象的导出,例如

import('/modules/myModule.mjs')
  .then((module) => {
    // Do something with the module.
  });

——部分信息来自:《代码大全2》Table-DrivenMethods 表驱动法,MDN,阮一峰博客