MVC與JS模塊化

經(jīng)典MVC模式中,M是指業(yè)務(wù)模型,V是指用戶界面,C則是控制器,使用MVC的目的是將M和V的實(shí)現(xiàn)代碼分離,從而使同一個(gè)程序可以使用不同的表現(xiàn)形式。其中,View的定義比較清晰,就是用戶界面。

1.MVC的三層結(jié)構(gòu)

1.1 M

M即model模型,是指模型表示業(yè)務(wù)規(guī)則(也就是程序需要操作的數(shù)據(jù)或信息)。在MVC的三個(gè)部件中,模型擁有最多的處理任務(wù)。被模型返回的數(shù)據(jù)是中立的,模型與數(shù)據(jù)格式無關(guān),這樣一個(gè)模型能為多個(gè)視圖提供數(shù)據(jù),由于應(yīng)用于模型的代碼只需寫一次就可以被多個(gè)視圖重用,所以減少了代碼的重復(fù)性。
JS代碼示例

const m = {    //  模擬數(shù)據(jù)模型
  data: {     //  使用的數(shù)據(jù)
    n: parseInt(localStorage.getItem('n'))
  },
  create() {},
  delete() {},
  update(data) {     //  修改數(shù)據(jù)
    Object.assign(m.data, data)
    eventBus.trigger('m:updated')
    localStorage.setItem('n', m.data.n)
  },
  get() {}
}

1.2 V

V即View視圖,是指用戶看到并與之交互的界面。比如由html元素組成的網(wǎng)頁界面,或者軟件的客戶端界面。MVC的好處之一在于它能為應(yīng)用程序處理很多不同的視圖。當(dāng)模型的數(shù)據(jù)發(fā)生變化,視圖相應(yīng)地刷新自己展示出來的頁面。
JS代碼示例

const v = {    //  視圖相關(guān)代碼
  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控制器,是指控制器接受用戶的輸入并調(diào)用模型和視圖去完成用戶的需求,控制器本身不輸出任何東西和做任何處理。它只是接收請求并決定調(diào)用哪個(gè)模型構(gòu)件去處理請求,然后再確定用哪個(gè)視圖來顯示返回的數(shù)據(jù)。
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)
    }
  }
}
三者關(guān)系示意圖
MVC.png

Controller通過調(diào)用相應(yīng)的方法改變Model數(shù)據(jù)模型中的數(shù)據(jù)等,數(shù)據(jù)模型Model的改變時(shí),使視圖隨之變化,視圖由于用戶的點(diǎn)擊觸發(fā)又會通過Controller去改變數(shù)據(jù)模型Model,這是一個(gè)循環(huán)的過程。

2. EventBus

當(dāng)兩個(gè)組件之間毫無關(guān)聯(lián),或者他們之間結(jié)構(gòu)復(fù)雜,但此時(shí)需要傳遞數(shù)據(jù),就需要用到件總線 EventBus的概念。
EventBus能夠簡化各組件間的通信,讓我們的代碼書寫變得簡單,能有效的分離事件發(fā)送方和接收方(也就是解耦的意思),能避免復(fù)雜和容易出錯(cuò)的依賴性和生命周期問題。
EventBus基本的api有 on(監(jiān)聽事件),trigger(emit)(觸發(fā)事件),off(取消監(jiān)聽)方法。用于模塊間的通訊,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. 表驅(qū)動編程

表驅(qū)動方法是一種使你可以在表(哈希表)中查找信息,而不必用邏輯語句(if 或 case)來把他們找出來的方法。
表驅(qū)動編程的意義在于邏輯與數(shù)據(jù)的分離。
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)
  })
}

將其中重復(fù)部分單獨(dú)使用,相同參數(shù)的不同變量提取出來合成一個(gè)哈希表,使邏輯與數(shù)據(jù)分離。

  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模塊化語法

模塊化開發(fā)使代碼藕合度降低,模塊化的意義在于最大化的設(shè)計(jì)重用,以最少的模塊、零部件,更快速的滿足更多的個(gè)性化需求。因?yàn)橛辛四K,我們就可以更方便地使用別人的代碼,想要什么功能,就加載什么模塊。但總不能隨便寫吧,總得有規(guī)范讓大家遵守吧。因此ES6出現(xiàn)了模塊化
export(導(dǎo)出)、import(引入)命令
export命令用于規(guī)定模塊的對外接口。
一個(gè)模塊就是一個(gè)獨(dú)立的文件。該文件內(nèi)部的所有變量,外部無法獲取。如果你希望外部能夠讀取模塊內(nèi)部的某個(gè)變量,就必須使用export關(guān)鍵字輸出該變量。
export輸出變量的寫法可以查看cdn文檔。
export命令可以出現(xiàn)在模塊的任何位置,只要處于模塊頂層就可以。如果處于塊級作用域內(nèi),就會報(bào)錯(cuò),下面的import命令也是如此。
import命令用于輸入其他模塊提供的功能。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 淺談MVC與JS模塊化 MVC是一種架構(gòu)設(shè)計(jì)模式,在之前的傳統(tǒng)后端語言中被應(yīng)用,用于構(gòu)建桌面和服務(wù)器端應(yīng)用程序,現(xiàn)...
    雨溪灘閱讀 484評論 0 1
  • 模塊化 將頁面中各部分執(zhí)行邏輯抽取出來單獨(dú)寫在一個(gè)js文件模塊。 模塊調(diào)用 在模塊中不要使用var聲明變量(會變量...
    千反田愛瑠愛好者閱讀 1,119評論 0 0
  • 這是一個(gè)有關(guān)安卓MVC框架模式的短系列,目的是思索和分析安卓中MVC模式更為真實(shí)的一面。 系列: 安卓中MVC模式...
    CysionLiu閱讀 577評論 0 8
  • 在目前的編程開發(fā)的教學(xué)中,大家往往關(guān)心的是語言、語句、對象等概念和編寫方法,卻往往忽視了開發(fā)思想的構(gòu)建。接下來的文...
    阿啊阿吖丁閱讀 811評論 0 0
  • 一、 MVC 設(shè)計(jì)模式 1. 設(shè)計(jì)模式 設(shè)計(jì)模式,是通用代碼(組織方式)的一種統(tǒng)稱 2. MVC 是什么 MVC ...
    x___h閱讀 425評論 0 0

友情鏈接更多精彩內(nèi)容