国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

javascript 觀察者(發(fā)布訂閱)模式詳解

anonymoussf / 1963人閱讀

摘要:寫給讀者的話本人是千千萬萬前端小白中的一員,所以對前端小白的痛苦感同身受,面對一個(gè)新的知識點(diǎn),很多時(shí)候感到束手無策。

寫給讀者的話

本人是千千萬萬前端小白中的一員,所以對前端小白的痛苦感同身受,面對一個(gè)新的知識點(diǎn),很多時(shí)候感到束手無策。網(wǎng)上搜資料,有的不全,有的看不懂,所以本人作為小白,很有義務(wù)將自己覺得理解了的知識點(diǎn)盡可能的解釋的通熟易懂,恨不得一個(gè)字一個(gè)字的解釋。但是別人的終究是別人的,把它變成自己的才是正道,希望此文能幫助像我一樣的人更好的理解mvc,一起加油吧

先上demo代碼,下面有詳盡分析

index.js

function Event(sender) {
    this._sender = sender;
    this._listeners = [];
}

Event.prototype = {
    constructor : Event,
    attach: function (listener) {
        this._listeners.push(listener);
    },
    notify: function (args) {
        var index;

        for (index = 0; index < this._listeners.length; index += 1) {
            this._listeners[index](this._sender, args);
        }
    }
};

function ListModel(items) {
    this._items = items;
    this._selectedIndex = -1;

    this.itemAdded = new Event(this);
    this.itemRemoved = new Event(this);
    this.selectedIndexChanged = new Event(this);
}

ListModel.prototype = {
    constructor : ListModel,
    getItems: function () {
        return [].concat(this._items);
    },

    addItem: function (item) {
        this._items.push(item);
        this.itemAdded.notify({
            item: item
        });
    },

    removeItemAt: function (index) {
        var item;

        item = this._items[index];
        this._items.splice(index, 1);
        this.itemRemoved.notify({
            item: item
        });
        if (index === this._selectedIndex) {
            this.setSelectedIndex(-1);
        }
    },

    getSelectedIndex: function () {
        return this._selectedIndex;
    },

    setSelectedIndex: function (index) {
        var previousIndex;

        previousIndex = this._selectedIndex;
        this._selectedIndex = index;
        this.selectedIndexChanged.notify({
            previous: previousIndex
        });
    }
};

function ListView(model, elements) {
    this._model = model;
    this._elements = elements;

    this.listModified = new Event(this);
    this.addButtonClicked = new Event(this);
    this.delButtonClicked = new Event(this);

    var _this = this;

    // attach model listeners
    this._model.itemAdded.attach(function () {
        _this.rebuildList();
    });
    this._model.itemRemoved.attach(function () {
        _this.rebuildList();
    });

    // attach listeners to HTML controls
    this._elements.list.change(function (e) {
        _this.listModified.notify({
            index: e.target.selectedIndex
        });
    });
    this._elements.addButton.click(function () {
        _this.addButtonClicked.notify();
    });
    this._elements.delButton.click(function () {
        _this.delButtonClicked.notify();
    });
}

ListView.prototype = {
    constructor : ListView,
    show: function () {
        this.rebuildList();
    },

    rebuildList: function () {
        var list, items, key;

        list = this._elements.list;
        list.html("");

        items = this._model.getItems();
        for (key in items) {
            if (items.hasOwnProperty(key)) {
                list.append($(""));
            }
        }
        this._model.setSelectedIndex(-1);
    }
};

function ListController(model, view) {
    this._model = model;
    this._view = view;

    var _this = this;

    this._view.listModified.attach(function (sender, args) {
        _this.updateSelected(args.index);
    });

    this._view.addButtonClicked.attach(function () {
        _this.addItem();
    });

    this._view.delButtonClicked.attach(function () {
        _this.delItem();
    });
}

ListController.prototype = {
    constructor : ListController,
    addItem: function () {
        var item = window.prompt("Add item:", "");
        if (item) {
            this._model.addItem(item);
        }
    },

    delItem: function () {
        var index;

        index = this._model.getSelectedIndex();
        if (index !== -1) {
            this._model.removeItemAt(this._model.getSelectedIndex());
        }
    },

    updateSelected: function (index) {
        this._model.setSelectedIndex(index);
    }
};

$(function () {
    var model = new ListModel(["PHP", "JavaScript"]),
        view = new ListView(model, {
            "list": $("#list"),
            "addButton": $("#plusBtn"),
            "delButton": $("#minusBtn")
        }),
        controller = new ListController(model, view);

    view.show();
});

index.html




    
    MVC


    
MVC模式說明:

model層和view層都繼承了觀察者類,觀察者類中包含訂閱和發(fā)布方法

model層定義了底層操作,包括對數(shù)據(jù)的增刪改查

view層綁定了增刪改事件,一旦所綁定的事件發(fā)生,就調(diào)用觀察者類中的發(fā)布方法發(fā)布消息;同時(shí)又訂閱了model層數(shù)據(jù)的變動,一旦所訂閱的model層的數(shù)據(jù)發(fā)生變化,就調(diào)用view層自身方法更新數(shù)據(jù)顯示

controller層訂閱了view層的增刪改事件,一旦所訂閱的事件發(fā)布了,就調(diào)用自身的方法經(jīng)過業(yè)務(wù)邏輯的處理,調(diào)用相應(yīng)的model層的方法

針對代碼做具體分析:

見下圖:

首先頁面加載執(zhí)行初始化代碼,執(zhí)行完成后頁面上會有一個(gè)列表,里面包含兩個(gè)選項(xiàng):PHP和Javascript,然后底下有"+"和"-"兩個(gè)按鈕,以點(diǎn)擊"+"為例,流程分析開始:

首先定義了一個(gè)觀察者Event構(gòu)造函數(shù)

view層中綁定了增刪改事件,同時(shí)訂閱了model層數(shù)據(jù)改動事件;

我們點(diǎn)擊"+"號按鈕,觸發(fā)了view層中的addButton的click事件,然后addButtonClicked調(diào)用觀察者構(gòu)造函數(shù)的發(fā)布方法notify()發(fā)布消息,代碼如下:

    this._elements.addButton.click(function () {
        _this.addButtonClicked.notify();
    });
    
4.由于在controller層中訂閱了view層的addButtonClicked發(fā)布的消息,將addItem()保存在其對應(yīng)的listener數(shù)組中,所以此時(shí)執(zhí)行_this.addItem(),代碼如下:
    this._view.addButtonClicked.attach(function () {
        _this.addItem();
    });
    
5.在controller層中的addItem()方法中,如果有item輸入,就調(diào)用model層中的addItem(item)并傳入item,代碼如下:
    addItem: function () {
        var item = window.prompt("Add item:", "");
        if (item) {
           this._model.addItem(item);
        }
    }
    
6.在model層中的itemAdd()方法中,獲取到controller層中傳過來的item之后,將其保存到this.item數(shù)組中,然后model層中的item調(diào)用notify()發(fā)布消息,代碼如下:
    addItem: function (item) {
        this._items.push(item);
        this.itemAdded.notify({
            item: item
        });
    }
    
7.由于在view層中訂閱了model層的itemAdd發(fā)布的消息,將rebuildList()保存在其對應(yīng)的listener數(shù)組中,所以此時(shí)執(zhí)行_this.rebuildList(),代碼如下:
    this._model.itemAdded.attach(function () {
        _this.rebuildList();
    });
    
8.view層中的rebuildList()干的事情就是每次都先清空列表內(nèi)容,然后重新獲取內(nèi)容,再循環(huán)添加到列表中,最后調(diào)用model層中的setSelectedIndex(-1)把選中項(xiàng)的index還原為-1,代碼如下:
    rebuildList: function () {
        var list, items, key;
        list = this._elements.list;
        list.html("");
        items = this._model.getItems();
        for (key in items) {
            if (items.hasOwnProperty(key)) {
                list.append($(""));
            }
        }
        this._model.setSelectedIndex(-1);
    }
    
9.model層中的setSelectedIndex()干的事情就是把上一次的選中項(xiàng)的index和當(dāng)前選中項(xiàng)的index進(jìn)行交換,然后model層中的selectedIndexChanged調(diào)用notify()發(fā)布消息,代碼如下:
    setSelectedIndex: function (index) {
        var previousIndex;
        previousIndex = this._selectedIndex;
        this._selectedIndex = index;
        this.selectedIndexChanged.notify({
            previous: previousIndex
        });
    }
    
10.你會發(fā)現(xiàn)view層中沒有對selectedIndexChanged的訂閱,那寫起來干嘛呢?就是留著以后進(jìn)行擴(kuò)展用的,你可以繼續(xù)按照這個(gè)模式寫下去
MVC的優(yōu)點(diǎn):

耦合性低:視圖層和業(yè)務(wù)層分離了,如果頁面上顯示改變的話,直接在視圖層更改即可,不用動模型層和控制層上的代碼;也就是視圖層 與 模型層和控制層

已經(jīng)分離了;所以很容易改變應(yīng)用層的數(shù)據(jù)層和業(yè)務(wù)規(guī)則。

可維護(hù)性:分離視圖層和業(yè)務(wù)邏輯層也使得WEB應(yīng)用更易于維護(hù)和修改。

MVC的缺點(diǎn):

個(gè)人覺得適合于大型項(xiàng)目,對于中小型項(xiàng)目并不適合,因?yàn)橐獙?shí)現(xiàn)一個(gè)簡單的增刪改操作,只需要一點(diǎn)點(diǎn)JS代碼,但是MVC模式代碼量明顯增加了。

希望此文對你有幫助,如有疑問和錯(cuò)誤,請告訴我,謝謝!

參考資料:

https://alexatnet.com/article...

http://web.jobbole.com/84945/

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/82541.html

相關(guān)文章

  • JavaScript 發(fā)布-訂閱模式

    摘要:發(fā)布訂閱模式訂閱者把自己想訂閱的事件注冊到調(diào)度中心,當(dāng)發(fā)布者發(fā)布該事件到調(diào)度中心,也就是該事件觸發(fā)時(shí),由調(diào)度中心統(tǒng)一調(diào)度訂閱者注冊到調(diào)度中心的處理代碼。 發(fā)布-訂閱模式,看似陌生,其實(shí)不然。工作中經(jīng)常會用到,例如 Node.js EventEmitter 中的 on 和 emit 方法;Vue 中的 $on 和 $emit 方法。他們都使用了發(fā)布-訂閱模式,讓開發(fā)變得更加高效方便。 一...

    13651657101 評論0 收藏0
  • JavaScript設(shè)計(jì)模式發(fā)布-訂閱模式察者模式)-Part1

    摘要:設(shè)計(jì)模式與開發(fā)實(shí)踐讀書筆記。發(fā)布訂閱模式又叫觀察者模式,它定義了對象之間的一種一對多的依賴關(guān)系。附設(shè)計(jì)模式之發(fā)布訂閱模式觀察者模式數(shù)據(jù)結(jié)構(gòu)和算法系列棧隊(duì)列優(yōu)先隊(duì)列循環(huán)隊(duì)列設(shè)計(jì)模式系列設(shè)計(jì)模式之策略模式 《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》讀書筆記。 發(fā)布-訂閱模式又叫觀察者模式,它定義了對象之間的一種一對多的依賴關(guān)系。當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴它的對象都將得到通知。 例...

    muzhuyu 評論0 收藏0
  • JavaScript 設(shè)計(jì)模式(六):察者模式發(fā)布訂閱模式

    摘要:觀察者模式維護(hù)單一事件對應(yīng)多個(gè)依賴該事件的對象關(guān)系發(fā)布訂閱維護(hù)多個(gè)事件主題及依賴各事件主題的對象之間的關(guān)系觀察者模式是目標(biāo)對象直接觸發(fā)通知全部通知,觀察對象被迫接收通知。 觀察者模式(Observer) 觀察者模式:定義了對象間一種一對多的依賴關(guān)系,當(dāng)目標(biāo)對象 Subject 的狀態(tài)發(fā)生改變時(shí),所有依賴它的對象 Observer 都會得到通知。 簡單點(diǎn):女神有男朋友了,朋友圈曬個(gè)圖,甜...

    bingo 評論0 收藏0
  • JavaScript 察者模式

    摘要:生活中的觀察者模式就如我們在專賣店預(yù)定商品如蘋果手機(jī),我們會向?qū)Yu店提交預(yù)定申請,然后店家受申請,正常這樣就完事了。中的觀察者模式在中觀察者模式的實(shí)現(xiàn)主要用事件模型。缺點(diǎn)使用全局的觀察者模式會明顯降低對象之間的聯(lián)系。 觀察者模式又叫做發(fā)布-訂閱模式。這是一種一對多的對象依賴關(guān)系,當(dāng)被依賴的對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都將得到通知。 生活中的觀察者模式 就如我們在專賣店預(yù)定商...

    zhigoo 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<