簡(jiǎn)單實(shí)現(xiàn)前端MVC框架

MVC/MVP/MVVM的區(qū)別

1. MVC

傳統(tǒng)的MVC主要分為三部分
? View 傳送指令到 Controller
? Controller 完成業(yè)務(wù)邏輯后存谎,要求 Model 改變狀態(tài)
? Model 將新的數(shù)據(jù)發(fā)送到 View,用戶得到反饋

MVC通用架構(gòu)

實(shí)際項(xiàng)目往往會(huì)更靈活贵白,比如Backbone 索性取消了 Controller高蜂,只保留一個(gè) Router(路由器) 。

2. MVP

MVP 模式將 Controller 改名為 Presenter,同時(shí)改變了通信方向。
? 各部分之間的通信媚狰,都是雙向的。
? View 與 Model 不發(fā)生聯(lián)系妄痪,都通過(guò) Presenter 傳遞哈雏。
? View 非常薄楞件,不部署任何業(yè)務(wù)邏輯衫生,稱為"被動(dòng)視圖"(Passive View),即沒(méi)有任何主動(dòng)性土浸,而 Presenter非常厚罪针,所有邏輯都部署在那里。

MVP架構(gòu)圖
3. MVVM

唯一的區(qū)別是黄伊,它采用雙向綁定(data-binding):View的變動(dòng)泪酱,自動(dòng)反映在 ViewModel,反之亦然

MVVM架構(gòu)圖

實(shí)現(xiàn)model

01 初步
// Model 核心代碼
function Model(value) {
    this._value = typeof value === 'undefined' ? '' : value;
    this._listeners = [];
}
Model.prototype.set = function(value) {
    var self = this;
    self._value = value;
    // model中的值改變時(shí),應(yīng)通知注冊(cè)過(guò)的回調(diào)函數(shù)
    // 按照J(rèn)avascript事件處理的一般機(jī)制墓阀,我們異步地調(diào)用回調(diào)函數(shù)
    // 如果覺(jué)得setTimeout影響性能毡惜,也可以采用requestAnimationFrame
    setTimeout(function() {
        self._listeners.forEach(function(listener) {
            listener.call(self, value);
        });
    });
};
Model.prototype.watch = function(listener) {
    // 注冊(cè)監(jiān)聽(tīng)的回調(diào)函數(shù)
    this._listeners.push(listener);
};
// html 代碼:
<div id="div1"></div>

// 邏輯代碼:
(function() {
    var model = new Model();
    var div1 = document.getElementById('div1');
    model.watch(function(value) {
        div1.innerHTML = value;
    });
    model.set('hello, this is a div');
})();
02 抽離中間方法,進(jìn)一步簡(jiǎn)化
// 抽離中間方法
Model.prototype.bind = function(node) {
    // 將watch的邏輯和通用的回調(diào)函數(shù)放到這里
    this.watch(function(value) {
        node.innerHTML = value;
    });
};

// html代碼:
<div id="div1"></div>
<div id="div2"></div>

// 邏輯代碼:
(function() {
    var model = new Model();
    model.bind(document.getElementById('div1'));
    model.bind(document.getElementById('div2'));
    model.set('this is a div');
})();

實(shí)現(xiàn)controller

function Controller(callback) {
    var models = {};
    // 找到所有有bind屬性的元素
    var views = document.querySelectorAll('[data-bind]');
    // 將views處理為普通數(shù)組
    views = Array.prototype.slice.call(views, 0);
    views.forEach(function(view) {
        var modelName = view.getAttribute('data-bind');
        // 取出或新建該元素所綁定的model
        models[modelName] = models[modelName] || new Model();
        // 完成該元素和指定model的綁定
        models[modelName].bind(view);
    });
    // 調(diào)用controller的具體邏輯斯撮,將models傳入经伙,方便業(yè)務(wù)處理
    callback.call(this, models);
}

// html:
<div id="div1" data-bind="model1"></div>
<div id="div2" data-bind="model1"></div>

// 邏輯代碼:
new Controller(function (models) {
    var model1 = models.model1;
    model1.set('this is a div');
});

MVC完整版

function Model(value) {
    this._value = typeof value === 'undefined' ? '' : value;
    this._listeners = [];
}
Model.prototype.set = function(value) {
    var self = this;
    self._value = value;
    setTimeout(function() {
        self._listeners.forEach(function(listener) {
            listener.call(self, value);
        });
    });
};
Model.prototype.watch = function(listener) {
    this._listeners.push(listener);
};
Model.prototype.bind = function(node) {
    this.watch(function(value) {
        node.innerHTML = value;
    });
};

function Controller(callback) {
    var models = {};
    var views = Array.prototype.slice.call(document.querySelectorAll('[data-bind]'), 0);
    views.forEach(function(view) {
        var modelName = view.getAttribute('data-bind');
        (models[modelName] = models[modelName] || new Model()).bind(view);
    });
    callback.call(this, models);
}


// html:
<span data-bind="hour"></span> : <span data-bind="minute"></span> : <span bind="second"></span>

// controller:
new Controller(function (models) {
    function setTime() {
        var date = new Date();
        models.hour.set(date.getHours());
        models.minute.set(date.getMinutes());
        models.second.set(date.getSeconds());
    }
    setTime();
    setInterval(setTime, 1000);
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市勿锅,隨后出現(xiàn)的幾起案子帕膜,更是在濱河造成了極大的恐慌,老刑警劉巖溢十,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垮刹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡张弛,警方通過(guò)查閱死者的電腦和手機(jī)荒典,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吞鸭,“玉大人种蝶,你說(shuō)我怎么就攤上這事÷鞔螅” “怎么了螃征?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)透敌。 經(jīng)常有香客問(wèn)我盯滚,道長(zhǎng),這世上最難降的妖魔是什么酗电? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任魄藕,我火速辦了婚禮,結(jié)果婚禮上撵术,老公的妹妹穿的比我還像新娘背率。我一直安慰自己,他們只是感情好嫩与,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布寝姿。 她就那樣靜靜地躺著,像睡著了一般划滋。 火紅的嫁衣襯著肌膚如雪饵筑。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天处坪,我揣著相機(jī)與錄音根资,去河邊找鬼架专。 笑死,一個(gè)胖子當(dāng)著我的面吹牛玄帕,可吹牛的內(nèi)容都是我干的部脚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼裤纹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼睛低!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起服傍,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤钱雷,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后吹零,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體罩抗,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年灿椅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了套蒂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茫蛹,死狀恐怖操刀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情婴洼,我是刑警寧澤骨坑,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站柬采,受9級(jí)特大地震影響欢唾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜粉捻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一礁遣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肩刃,春花似錦祟霍、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至续语,卻和暖如春垂谢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疮茄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工滥朱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人力试。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓徙邻,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親畸裳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缰犁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容