Slide 1

Slide 1 text

UNDERSTANDING THE MVC MVP MVVM IN JAVASCRIPT

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

咦?默念?

Slide 4

Slide 4 text

Who am I ? I am Iron Man

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Jace Ju ⼤大澤⽉⽊木⼩小鐵

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

我不是前端工程師...

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

20 年前...

Slide 16

Slide 16 text

20 年前... 駭客正夯

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

MV*

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Code http://jsfiddle.net/EWbxg/

Slide 30

Slide 30 text

Model View &

Slide 31

Slide 31 text

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 資料的狀態

Slide 32

Slide 32 text

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 操作內部狀態的⾏行為

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

MVC

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

View 觀察 Model Controller 負責派送 Request 並控制 Model 的狀態 使⽤用者接觸的對象是 Controller MVC 架構 看報紙才知道

Slide 38

Slide 38 text

View Controller Model

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

View Controller Model View 向 Model 註冊

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

Code http://jsfiddle.net/uVBvq/

Slide 46

Slide 46 text

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 的參考

Slide 47

Slide 47 text

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 更新

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

myapp.View = function (controller) { // ... $incBtn.click(controller.increase); $decBtn.click(controller.decrease); }; View 將事件綁定在 Controller 的 Action

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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 註冊⾃自⼰己

Slide 52

Slide 52 text

myapp.Controller = function () { // ... this.increase = function () { model.add(1); model.notify(); }; this.decrease = function () { model.sub(1); model.notify(); }; }; Controller Controller 負責控制 Model

Slide 53

Slide 53 text

(function () { var controller = new myapp.Controller(); controller.init(); })(); Run 外界只接觸到 Controller

Slide 54

Slide 54 text

Model 不應該擁有 View 的參考 View 不容易測試 缺點

Slide 55

Slide 55 text

MVP 叫我嗎?

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

Supervising Controller Passive View MVP 類型

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

View Presenter Model

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

View Model Presenter Presenter 初始化 Model

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

Persenter 改變 並獲取 Model 狀態 View Model Presenter

Slide 65

Slide 65 text

使⽤用者看到 View 改變了輸出 View Model Presenter Presenter 將 Model 的狀態 更新到 View 上⾯面

Slide 66

Slide 66 text

簡單來說 要在發生某個事件後 我們才會知道 總統是隻水母

Slide 67

Slide 67 text

Code http://jsfiddle.net/tgHra/

Slide 68

Slide 68 text

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 不需要觀察者模式

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

(function () { var view = new myapp.View(); view.init(); })(); Run 外界只接觸到 View

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

MVVM

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

ViewModel : 將資料轉換成視覺元件可⽤用的狀態 View : 包含 bind 邏輯的樣版 Model : 跟資料來源溝通⽤用 MVVM 架構

Slide 77

Slide 77 text

ViewModel ⼀一有變化就更新 View View ⼀一有輸⼊入值就更新 ViewModel Data-Binding 由 Framework 來處理 不必⾃自⼰己找元素 Two-way Data Binding

Slide 78

Slide 78 text

Code http://jsfiddle.net/fVAcE/

Slide 79

Slide 79 text


+ - View (knockout.js) View (Template) 透過 HTML 屬性來與 ViewModel 結合

Slide 80

Slide 80 text

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 結合起來

Slide 81

Slide 81 text

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 元素上

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

需要隨時監控 View 的狀態 效能會受到影響 效能掌握在 Framework ⼿手上 Data-Binding 的錯誤要在 Runtime 時才能發現 MVVM 缺點

Slide 84

Slide 84 text

EVENT

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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 加到事件的庫裡

Slide 91

Slide 91 text

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 ⼀一⼀一找出來執⾏行

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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 觸發事件

Slide 94

Slide 94 text

取代了觀察者模式 Model, View 透過 Event 溝通 Controller, Presenter, ViewModel 可以更靈活 隱藏在 Framework 裡 Event + MV*

Slide 95

Slide 95 text

Conclusion

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

YOU THANK