$30 off During Our Annual Pro Sale. View Details »

Understanding the MVC,MVP,MVVM in JavaScript

Understanding the MVC,MVP,MVVM in JavaScript

JSDC 2013 Slides

大澤木小鐵

May 19, 2013
Tweet

More Decks by 大澤木小鐵

Other Decks in Technology

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