實例說明MVC,MVP,MVVM架構

分類:IT技術 時間:2017-10-04

很早就知道有這三個概念,但是一直都不清楚是怎麽回事,在網上搜索,都是泛泛而談,沒有具體例子,新手是看不懂的,直到找到這篇文章,我對這三個架構有了更清楚的了解。

從一個簡單的例子去研究這三個架構。

註意,MVC,MVP,MVVM中的C,P,VM,下文都要controller指代。

需求如下

界面上顯示100,以及兩個按鈕,其中一個點一下加1,另外一個點一下減1

如圖

誠然,這麽簡單的需求,並不需要用什麽架構去完成,可是如果是復雜的需求,要長篇大論才能說完,所以只拿簡單的來做例子,實際開發中,你在完成一個需求之前,是需要好好掂量是否要用架構,要的話,用什麽架構(不局限於這三個),架構裏面又要用什麽設計模式等等。經過我的實踐,發現,即使是架構改變了,view是可以完全不變的,所以先展現view層的代碼。

html部分

<span id="text">100</span>
<button id="upBtn">up</button>
<button id="downBtn">down</button>

js部分

function $(id) {
  return document.querySelector(`#${id}`);
}
function View(controller) {
  const upBtn = $('upBtn');
  const downBtn = $('downBtn');
  const textSpan = $('text');

  this.render = function(model) {
    textSpan.innerHTML = model.getValue();
  }
  upBtn.onclick = controller.up;
  downBtn.onclick = controller.down;
}

render方法是核心,方法名稱不能改(後面要依賴這個render方法),其中要實現數據的展示邏輯,然後是一些點擊事件的綁定

MVC

model層

function Model() {
  let value = 100;
  this.up = function() {
    value += 1;
  };
  this.down = function() {
    value -= 1;
  };
  this.getValue = http://www.cnblogs.com/maoscut/p/function() {
    return value;
  };
}

保存數據,並提供訪問,修改數據的方法,如果僅僅是這樣,那麽當model改變時,view是不知道的,所以需要讓model去通知view,我數據改變了,你要更新了。怎麽做呢?利用觀察者模式。在model中,增加一個數組views,去保存這個model對應的視圖,在修改數據的時候,遍歷views數組,調用每個view的render方法,參數是自己。

修改後的model

function Model() {
  let value = 100;
  const self = this;
  const views = [];
  this.up = function() {
    value += 1;
  };
  this.down = function() {
    value -= 1;
  };
  this.getValue = http://www.cnblogs.com/maoscut/p/function() {
    return value;
  };
  this.broadcast = function() {
    views.forEach(view => view.render(self));
  };
  this.subscribe = function(cb) {
    views.push(cb);
  }
}

仔細看修改後的model,雖然增加了通知的方法(broadcast),但是在修改數據的方法(up和down)中並沒有去通知視圖。這個工作是由controller承擔的,另外把view註冊到model中,也是controller做的。

controller層

function Controller() {
  let view = null;
  let model = null;
  this.up = function() {
    // 修改數據
    model.up();
    // 通知視圖
    model.broadcast();
  };
  this.down = function() {
    model.down();
    model.broadcast();
  }
  this.init = function() {
    view = new View(this);
    model = new Model();
    // 把視圖註冊到model中
    model.subscribe(view);
  }
}

可以看到,controller把自己傳給了view去創建視圖,同時保存引用,創建model後,把view註冊到model中。同時實現了,改變數據,通知視圖的工作。

請一定要好好理解MVC,後面的MVP,MVVM都只是稍加修改而已。

MVP

在MVC中,改變數據,通知視圖,都是在controller做的,註冊視圖,以及通知視圖,這兩個方法的實現,都是model完成的,既然model負責數據處理,這兩個工作實際上和改變數據是沒關系的,把他們都轉移到controller中,不僅可以讓model層專註於數據處理,同時也方便多個視圖共用一個controller

model層

function Model() {
  let value = 100;
  this.up = function() {
    value += 1;
  };
  this.down = function() {
    value -= 1;
  };
  this.getValue = http://www.cnblogs.com/maoscut/p/function() {
    return value;
  };
}

model層更小了,刪除了註冊,通知方法,只保存數據和提供獲取,修改數據的方法

controller層

function Controller() {
  let views = [];
  let model = null;
  function broadcast() {
    views.forEach(view => view.render(model));
  }
  this.up = function() {
    model.up();
    broadcast();
  };
  this.down = function() {
    model.down();
    broadcast();
  }
  this.init = function() {
    views.push(new View(this));
    model = new Model();
  }
}

controller,增加了廣播方法,該方法的實現和調用都在controller中,另外,如果想多個視圖共用一個controller,如果這多個視圖都是同一個model,上面代碼能夠勝任,如果是這多個視圖是不同的model,那就要自己去實現好view和model的對應關系了(要用map來存儲對應關系,一個數組做不到)。

MVVM

可以看到,在MVP中,model也有一個up方法,controller也有一個up方法,只是增加了一個廣播方法的調用。是不是有些重復呢?把這兩個類似的方法整合到controller,model只負責保存數據,不實現修改數據的邏輯,這就是MVVM了,極大地精簡model

model層

function Model() {
  let value = 100;
  this.getValue = http://www.cnblogs.com/maoscut/p/function() {
    return value;
  };
  this.setValue = http://www.cnblogs.com/maoscut/p/function(v) {
    value = v;
  }
}

其實,不用函數,單純地用一個變量,也是可以的,但是為了view層不變,view層中依賴model的getValue方法,所以這裏還是用函數去實現model

controller層

function Controller() {
  let views = [];
  let model = null;
  function broadcast() {
    views.forEach(view => view.render(model));
  }
  this.up = function() {
    model.setValue(model.getValue() + 1);
    broadcast();
  };
  this.down = function() {
    model.setValue(model.getValue() - 1);
    broadcast();
  }
  this.init = function() {
    views.push(new View(this));
    model = new Model();
  }
}

精簡model的代價是controller要做更多的事情,實現修改數據的邏輯,通知視圖。如果用框架,react或者vue,通知視圖這部分框架會幫你實現,只要實現數據修改的邏輯就好了。

至此,三個架構都講完了,如果錯誤,歡迎討論。

代碼可在github上下載,需要node環境。

參考資料:http://www.cnblogs.com/zhouyangla/p/6936455.html


Tags: 架構 controller quot function 三個 需求

文章來源:


ads
ads

相關文章
ads

相關文章

ad