Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Understanding the MVC,MVP,MVVM in JavaScript

Understanding the MVC,MVP,MVVM in JavaScript

JSDC 2013 Slides

F830ec52d5bf72ee64fd1a43a6a82a49?s=128

大澤木小鐵

May 19, 2013
Tweet

Transcript

  1. UNDERSTANDING THE MVC MVP MVVM IN JAVASCRIPT

  2. None
  3. 咦?默念?

  4. Who am I ? I am Iron Man

  5. Who am I ? I am Iron Man 閃到腰的

  6. Jace Ju ⼤大澤⽉⽊木⼩小鐵

  7. ⺫⽬目前正在領 微博的薪⽔水

  8. 我不是前端工程師...

  9. 我不是前端工程師... 我也不是社工...

  10. 我不是前端工程師... 我也不是社工... 我只是個打雜的...

  11. 我不是前端工程師... 我也不是社工... 我只是個打雜的... System, DBA, Backend... HTML, CSS, JavaScript... 我都只會一點點...

    Orz
  12. 雖然我是這次 講師群裡最弱的

  13. 雖然我是這次 講師群裡最弱的 但我有 GitHub https://github.com/jaceju

  14. 不過我喜歡分享 自己學到的給大家 然後也從大家 那邊學到很棒的東西 ^ ^

  15. 20 年前...

  16. 20 年前... 駭客正夯

  17. 20 年前... 駭客正夯 GUI (圖形化操作介面)

  18. 視覺控制項與資料整合 強化使⽤用者對資料的印象 事件驅動 配合 Framework / IDE GUI

  19. 常常會在事件處理⽅方法裡 包含了資料運算邏輯 每個元件之間的互動 都放在⼀一個⽅方法裡 問題

  20. MVC / MVP / MVVM 就是要解決這些問題

  21. 瞭解 MVC / MVP / MVVM 的基本原理 JavaScript 如何實作它們 所以今天...

  22. MV*

  23. MV* ⺫⽬目的 視覺邏輯 流程邏輯 資料運算邏輯

  24. 從資料運算邏輯中分離視覺邏輯 MV* ⺫⽬目的 視覺邏輯 流程邏輯 資料運算邏輯

  25. 從資料運算邏輯中分離視覺邏輯 從視覺邏輯中分離流程邏輯 MV* ⺫⽬目的 視覺邏輯 流程邏輯 資料運算邏輯

  26. 分離關注點 團隊合作 便於測試 推卸責任

  27. 團隊合作 便於測試 推卸責任 分離關注點 釐清問題點

  28. Example 0px + - span#num button#increase button#decrease

  29. Code http://jsfiddle.net/EWbxg/

  30. Model View &

  31. var myapp = {}; myapp.Model = function () { var

    val = 0; this.add = function (v) { if (val < 100) val += v; }; this.sub = function (v) { if (val > 0) val -= v; }; this.getVal = function () { return val; }; }; Model 資料的狀態
  32. var myapp = {}; myapp.Model = function () { var

    val = 0; this.add = function (v) { if (val < 100) val += v; }; this.sub = function (v) { if (val > 0) val -= v; }; this.getVal = function () { return val; }; }; Model 操作內部狀態的⾏行為
  33. myapp.View = function () { var $num = $('#num'); var

    $incBtn = $('#increase'); var $decBtn = $('#decrease'); this.render = function (model) { $num.text(model.getVal() + 'px'); }; }; View 管理視覺元件
  34. View myapp.View = function () { var $num = $('#num');

    var $incBtn = $('#increase'); var $decBtn = $('#decrease'); this.render = function (model) { $num.text(model.getVal() + 'px'); }; }; 呈現資料
  35. MVC

  36. 由 Xerox PARC 提出 MVC 簡史 http://huoding.com/2011/05/02/64 MVC 簡介

  37. View 觀察 Model Controller 負責派送 Request 並控制 Model 的狀態 使⽤用者接觸的對象是

    Controller MVC 架構 看報紙才知道
  38. View Controller Model

  39. (箭頭⽅方向表⽰示擁有該物件參考) View Controller Model Controller 初始化 Model 與 View

  40. View Controller Model View 向 Model 註冊

  41. View Controller Model 使⽤用者看到 View 的初始輸出

  42. View Controller Model 使⽤用者向 Controller 發出請求

  43. View Controller Model Controller 改變 Model 狀態 Model 再次 通知

    View
  44. View Controller Model 使⽤用者看到 View 改變了輸出

  45. Code http://jsfiddle.net/uVBvq/

  46. myapp.Model = function () { // ... var views =

    []; this.register = function (view) { views.push(view); } var self = this; this.notify = function () { for (var i = 0; i < views.length; i++) { views[i].render(self); } }; }; Model Model 擁有 View 的參考
  47. myapp.Model = function () { // ... var views =

    []; this.register = function (view) { views.push(view); } var self = this; this.notify = function () { for (var i = 0; i < views.length; i++) { views[i].render(self); } }; }; Model Model 有變化時通知 View 更新
  48. View myapp.View = function (controller) { // ... $incBtn.click(controller.increase); $decBtn.click(controller.decrease);

    }; 引⽤用 Controller 參考
  49. myapp.View = function (controller) { // ... $incBtn.click(controller.increase); $decBtn.click(controller.decrease); };

    View 將事件綁定在 Controller 的 Action
  50. myapp.Controller = function () { var model = null; var

    view = null; this.init = function () { model = new myapp.Model(); view = new myapp.View(this); model.register(view); model.notify(); }; }; Controller Controller 初始化 Model 與 View
  51. myapp.Controller = function () { var model = null; var

    view = null; this.init = function () { model = new myapp.Model(); view = new myapp.View(this); model.register(view); model.notify(); }; }; Controller View 向 Model 註冊⾃自⼰己
  52. myapp.Controller = function () { // ... this.increase = function

    () { model.add(1); model.notify(); }; this.decrease = function () { model.sub(1); model.notify(); }; }; Controller Controller 負責控制 Model
  53. (function () { var controller = new myapp.Controller(); controller.init(); })();

    Run 外界只接觸到 Controller
  54. Model 不應該擁有 View 的參考 View 不容易測試 缺點

  55. MVP 叫我嗎?

  56. 由 IBM 提出 Microsoft ASP.Net WebForms MVP 簡介

  57. 使⽤用者接觸的對象是 View Presenter 取代 Controller 派送的⾓角⾊色由 View 來扮演 MVP 結構

  58. Supervising Controller Passive View MVP 類型

  59. Passive View View 和 Model 不需要知道對⽅方 Presenter 的⼯工作量⽐比較⼤大 整體的可測試⽐比較好

  60. View Presenter Model

  61. View Model Presenter 使⽤用者看到 View 的初始輸出 View 初始化 Presenter

  62. View Model Presenter Presenter 初始化 Model

  63. View Model Presenter View 委派 Presenter 來 處理使⽤用者的請求 使⽤用者透過 View

    來發出請求
  64. Persenter 改變 並獲取 Model 狀態 View Model Presenter

  65. 使⽤用者看到 View 改變了輸出 View Model Presenter Presenter 將 Model 的狀態

    更新到 View 上⾯面
  66. 簡單來說 要在發生某個事件後 我們才會知道 總統是隻水母

  67. Code http://jsfiddle.net/tgHra/

  68. myapp.Model = function () { var val = 0; this.add

    = function (v) { if (val < 100) val += v; }; this.sub = function (v) { if (val > 0) val -= v; }; this.getVal = function () { return val; }; }; Model 不需要觀察者模式
  69. myapp.Presenter = function (view) { var _model = new myapp.Model();

    var _view = view; _view.render(_model.getVal()); this.increase = function () { _model.add(1); _view.render(_model.getVal()); }; this.decrease = function () { _model.sub(1); _view.render(_model.getVal()); }; }; Presenter Presenter 將 Model 內容 傳遞給 View
  70. myapp.View = function () { // ... this.init = function

    () { var presenter = new myapp.Presenter(this); $incBtn.click(presenter.increase); $decBtn.click(presenter.decrease); }; } View View 將請求委派給 Presenter
  71. (function () { var view = new myapp.View(); view.init(); })();

    Run 外界只接觸到 View
  72. 與 MVC 差異 適合維持狀態 View 與 Model 之間解耦

  73. 與 MVC 差異 適合維持狀態 View 與 Model 之間解耦

  74. MVVM

  75. 由 Microsoft 提出 Microsoft WPF Knockout.js http://blog.darkthread.net/ post-2012–05–09-knockout-js-intro.aspx MVVM 簡介

  76. ViewModel : 將資料轉換成視覺元件可⽤用的狀態 View : 包含 bind 邏輯的樣版 Model :

    跟資料來源溝通⽤用 MVVM 架構
  77. ViewModel ⼀一有變化就更新 View View ⼀一有輸⼊入值就更新 ViewModel Data-Binding 由 Framework 來處理

    不必⾃自⼰己找元素 Two-way Data Binding
  78. Code http://jsfiddle.net/fVAcE/

  79. <span id="num" data-bind="text: val"></span><br/> <button data-bind="click: increase">+</button> <button data-bind="click: decrease">-</button>

    View (knockout.js) View (Template) 透過 HTML 屬性來與 ViewModel 結合
  80. myapp.ViewModel = function () { var model = new myapp.Model();

    this.num = ko.observable(model.getVal()); this.val = ko.computed(function() { return this.num() + 'px'; }, this); }; ViewModel View 利⽤用觀察者模式 將 ViewModel 結合起來
  81. myapp.ViewModel = function () { // ... this.increase = function

    () { model.add(1); this.num(model.getVal()); }; this.decrease = function () { model.sub(1); this.num(model.getVal()); }; }; ko.applyBindings(new myapp.ViewModel()); ViewModel ViewModel 操作 Model 並將資料 binding 到 View 元素上
  82. myapp.ViewModel = function () { // ... this.increase = function

    () { model.add(1); this.num(model.getVal()); }; this.decrease = function () { model.sub(1); this.num(model.getVal()); }; }; ko.applyBindings(new myapp.ViewModel()); ViewModel 透過 Framework 結合 View 與 ViewModel
  83. 需要隨時監控 View 的狀態 效能會受到影響 效能掌握在 Framework ⼿手上 Data-Binding 的錯誤要在 Runtime

    時才能發現 MVVM 缺點
  84. EVENT

  85. ⽤用事件代替引⽤用, 解耦物件之間的關係 維繫事件與 callbacks 射後不理 Event 概念

  86. callback Object Event callback callback 註冊事件對應的 callback (on / bind)

  87. Object Event 物件觸發事件 (trigger) callback callback callback

  88. Object Event Event 呼叫事件 對應的 callback callback callback callback

  89. Code http://jsfiddle.net/pm3xr/ 從 Backbone.js 抽出來簡化

  90. var Event = { _events: {}, on: function(name, callback, context)

    { ! this._events || (this._events = {}); ! var events = this._events[name] ! ! ! || (this._events[name] = []); ! events.push({ ! ! callback: callback, ! ! ctx: context ! }); } }; Event.on 將 callback 及 context 加到事件的庫裡
  91. Event.trigger var Event = { // ... trigger: function(name) {

    ! var events = this._events[name]; ! for (var i = 0; i < events.length; i++) { ! ! (ev = events[i]).callback.call(ev.ctx); ! } } }; 將事件對應的 callback ⼀一⼀一找出來執⾏行
  92. Event.on('event1', function () { ! alert('callback 1'); }, this); Event.on('event1',

    function () { ! alert('callback 2'); }, this); Event.on('event2', function () { ! alert('callback 3'); }, this); Event.trigger('event1'); Event.trigger('event2'); Event Demo 事件綁定 callback
  93. Event.on('event1', function () { ! alert('callback 1'); }, this); Event.on('event1',

    function () { ! alert('callback 2'); }, this); Event.on('event2', function () { ! alert('callback 3'); }, this); Event.trigger('event1'); Event.trigger('event2'); Event Demo 觸發事件
  94. 取代了觀察者模式 Model, View 透過 Event 溝通 Controller, Presenter, ViewModel 可以更靈活

    隱藏在 Framework 裡 Event + MV*
  95. Conclusion

  96. 觀看的⾓角度與實作的⽅方式 邏輯分離 模組化 各位還是⽤用 Framework 吧 Points

  97. 前端工程... 會跟著各位一起成長的

  98. YOU THANK