美文网首页
MVC与JS模块化

MVC与JS模块化

作者: 茜Akane | 来源:发表于2022-01-15 17:53 被阅读0次

经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面。

1.MVC的三层结构

1.1 M

M即model模型,是指模型表示业务规则(也就是程序需要操作的数据或信息)。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
JS代码示例

const m = {    //  模拟数据模型
  data: {     //  使用的数据
    n: parseInt(localStorage.getItem('n'))
  },
  create() {},
  delete() {},
  update(data) {     //  修改数据
    Object.assign(m.data, data)
    eventBus.trigger('m:updated')
    localStorage.setItem('n', m.data.n)
  },
  get() {}
}

1.2 V

V即View视图,是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。当模型的数据发生变化,视图相应地刷新自己展示出来的页面。
JS代码示例

const v = {    //  视图相关代码
  el: null,
  html: `
  <div>
    <div class="output">
      <span id="number">{{n}}</span>
    </div>
    <div class="actions">
      <button id="add1">+1</button>
      <button id="minus1">-1</button>
      <button id="mul2">*2</button>
      <button id="divide2">÷2</button>
    </div>
  </div>
`,
  init(container) {
    v.el = $(container)
  },
  render(n) {
    if (v.el.children.length !== 0) v.el.empty()
    $(v.html.replace('{{n}}', n))
      .appendTo(v.el)
  }
}

1.3 C

C即controller控制器,是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。
JS代码示例

const c = {      //  控制器
  init(container) {
    v.init(container)
    v.render(m.data.n) // view = render(data)
    c.autoBindEvents()
    eventBus.on('m:updated', () => {
      console.log('here')
      v.render(m.data.n)
    })
  },
  events: {
    'click #add1': 'add',
    'click #minus1': 'minus',
    'click #mul2': 'mul',
    'click #divide2': 'div',
  },
  add() {
    m.update({n: m.data.n + 1})
  },
  div() {
    m.update({n: m.data.n / 2})
  },
  autoBindEvents() {
    for (let key in c.events) {
      const value = c[c.events[key]]
      const spaceIndex = key.indexOf(' ')
      const part1 = key.slice(0, spaceIndex)
      const part2 = key.slice(spaceIndex + 1)
      v.el.on(part1, part2, value)
    }
  }
}
三者关系示意图
MVC.png

Controller通过调用相应的方法改变Model数据模型中的数据等,数据模型Model的改变时,使视图随之变化,视图由于用户的点击触发又会通过Controller去改变数据模型Model,这是一个循环的过程。

2. EventBus

当两个组件之间毫无关联,或者他们之间结构复杂,但此时需要传递数据,就需要用到件总线 EventBus的概念。
EventBus能够简化各组件间的通信,让我们的代码书写变得简单,能有效的分离事件发送方和接收方(也就是解耦的意思),能避免复杂和容易出错的依赖性和生命周期问题。
EventBus基本的api有 on(监听事件),trigger(emit)(触发事件),off(取消监听)方法。用于模块间的通讯,view组件层面,父子组件、兄弟组件通信都可以使用eventbus 处理。
JS代码示例

//EventBus.js
class EventBus {
    constructor() {
        this._eventBus = $(window)
    }
    on(eventName, fn) {
        return this._eventBus.on(eventName, fn)
    }
    trigger(eventName, data) {
        return this._trigger.trigger(eventName, data)
    }
    off(eventName, fn) {
        return this._eventBus.off(eventName, fn)
    }
}
export default EventBus
//new.js
import EventBus from 'EventBus.js'
const e = new EventBus()
e.on()
e.trigger()
e.off()

3. 表驱动编程

表驱动方法是一种使你可以在表(哈希表)中查找信息,而不必用逻辑语句(if 或 case)来把他们找出来的方法。
表驱动编程的意义在于逻辑与数据的分离。
JS代码示例

bindEvents(){
  v.el.on('click', '#add1', () => {
    m.data.n += 1
    v.render(m.data.n)
  })
  v.el.on('click', '#minus1', () => {
    m.data.n -= 1
    v.render(m.data.n)
  })
  v.el.on('click', '#mul2', () => {
    m.data.n *= 2
    v.render(m.data.n)
  })
  v.el.on('click', '#divide2', () => {
    m.data.n /= 2
    v.render(m.data.n)
  })
}

将其中重复部分单独使用,相同参数的不同变量提取出来合成一个哈希表,使逻辑与数据分离。

  events: {
    "click #add1": "add",
    "click #minus1": "minus",
    "click #mul2": "mul",
    "click #divide2": "divide",
    "click #reset": "reset",
  },
  add() {
    m.update({ n: m.data.n + 1 })
  },
  minus() {
    m.update({ n: m.data.n - 1 })
  },
  mul() {
    m.update({ n: m.data.n * 2 })
  },
  divide() {
    m.update({ n: m.data.n / 2 })
  },
  autoBindEvents() {
    for (let key in c.events) {
      const value = c[c.events[key]]
      const spliceIndex = key.indexOf(" ")
      const part1 = key.slice(0, spliceIndex)
      const part2 = key.slice(spliceIndex + 1)
      v.el.on(part1, part2, value)
    }
  },

2. JS模块化语法

模块化开发使代码藕合度降低,模块化的意义在于最大化的设计重用,以最少的模块、零部件,更快速的满足更多的个性化需求。因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。但总不能随便写吧,总得有规范让大家遵守吧。因此ES6出现了模块化
export(导出)、import(引入)命令
export命令用于规定模块的对外接口。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
export输出变量的写法可以查看cdn文档。
export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,下面的import命令也是如此。
import命令用于输入其他模块提供的功能。

相关文章

  • Angular.js概括总结

    Angular.js 核心思想:MVC、指令系统、双向数据绑定、模块化 MVC是一种软件...

  • MVC与JS模块化

    经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同...

  • Angular.js学习笔记

    angular.js核心特性:1、MVC 2、模块化Module 3、指令系统 4、双向数据绑定 基本概念与用法:...

  • web前端学习计划

    前端学习的知识路线:原生js,使用jQuery及编写jQuery扩展,前端模版,前端mvc,模块化开发,mvvm开...

  • 代码写在export里和外面的区别

    在vue中,包括我们自己使用mvc实现模块化的时候,往往需要将每个js或者vue作为独立的模块,然后将js代码写在...

  • 模块化开发 MVP View Presenter Model 与MVC区别: 视图层与业务层无直...

  • 代码优化

    优化代码的目的:提高运行速度; js代码优化: 代码重用 避免全局变量(全局变量,封闭空间,模块化,mvc..) ...

  • 牛刀小试

    一.规避Javascript多人开发函数重名问题? 1.命名空间. 2.封闭空间. 3.js模块化MVC(结构层,...

  • AngularJS学习笔记(一)模块、作用域、双向数据绑定

    AngularJS四大核心特性:MVC、模块化、指令系统、双向数据绑定。 MVC 好处:职责清晰,代码模块化,可复...

  • 模块化与 MVC

    一、代码模块化 定义模块化就是把一个复杂的代码段拆分成若干个小片段(模块),使实现不同功能的代码区分开,然后就可以...

网友评论

      本文标题:MVC与JS模块化

      本文链接:https://www.haomeiwen.com/subject/ocracrtx.html