日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

javascript 观察者(发布订阅)模式详解

發布時間:2024/4/17 javascript 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 javascript 观察者(发布订阅)模式详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫給讀者的話

本人是千千萬萬前端小白中的一員,所以對前端小白的痛苦感同身受,面對一個新的知識點,很多時候感到束手無策。網上搜資料,有的不全,有的看不懂,所以本人作為小白,很有義務將自己覺得理解了的知識點盡可能的解釋的通熟易懂,恨不得一個字一個字的解釋。但是別人的終究是別人的,把它變成自己的才是正道,希望此文能幫助像我一樣的人更好的理解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 listenersthis._model.itemAdded.attach(function () {_this.rebuildList();});this._model.itemRemoved.attach(function () {_this.rebuildList();});// attach listeners to HTML controlsthis._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($('<option>' + items[key] + '</option>'));}}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

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>MVC</title> </head> <body><select id="list" size="10" style="width: 10rem"></select><br/><button id="plusBtn"> + </button><button id="minusBtn"> - </button> </body> <script src="jquery-1.8.3.min.js"></script> <script src="index.js"></script> </html>

MVC模式說明:

  • model層和view層都繼承了觀察者類,觀察者類中包含訂閱和發布方法
  • model層定義了底層操作,包括對數據的增刪改查
  • view層綁定了增刪改事件,一旦所綁定的事件發生,就調用觀察者類中的發布方法發布消息;同時又訂閱了model層數據的變動,一旦所訂閱的model層的數據發生變化,就調用view層自身方法更新數據顯示
  • controller層訂閱了view層的增刪改事件,一旦所訂閱的事件發布了,就調用自身的方法經過業務邏輯的處理,調用相應的model層的方法
  • 針對代碼做具體分析:

    見下圖:

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

  • 首先定義了一個觀察者Event構造函數
  • view層中綁定了增刪改事件,同時訂閱了model層數據改動事件;
  • 我們點擊"+"號按鈕,觸發了view層中的addButton的click事件,然后addButtonClicked調用觀察者構造函數的發布方法notify()發布消息,代碼如下:
  • this._elements.addButton.click(function () {_this.addButtonClicked.notify();}); 4.由于在controller層中訂閱了view層的addButtonClicked發布的消息,將addItem()保存在其對應的listener數組中,所以此時執行_this.addItem(),代碼如下: this._view.addButtonClicked.attach(function () {_this.addItem();}); 5.在controller層中的addItem()方法中,如果有item輸入,就調用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數組中,然后model層中的item調用notify()發布消息,代碼如下: addItem: function (item) {this._items.push(item);this.itemAdded.notify({item: item});} 7.由于在view層中訂閱了model層的itemAdd發布的消息,將rebuildList()保存在其對應的listener數組中,所以此時執行_this.rebuildList(),代碼如下: this._model.itemAdded.attach(function () {_this.rebuildList();}); 8.view層中的rebuildList()干的事情就是每次都先清空列表內容,然后重新獲取內容,再循環添加到列表中,最后調用model層中的setSelectedIndex(-1)把選中項的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($('<option>' + items[key] + '</option>'));}}this._model.setSelectedIndex(-1);} 9.model層中的setSelectedIndex()干的事情就是把上一次的選中項的index和當前選中項的index進行交換,然后model層中的selectedIndexChanged調用notify()發布消息,代碼如下: setSelectedIndex: function (index) {var previousIndex;previousIndex = this._selectedIndex;this._selectedIndex = index;this.selectedIndexChanged.notify({previous: previousIndex});} 10.你會發現view層中沒有對selectedIndexChanged的訂閱,那寫起來干嘛呢?就是留著以后進行擴展用的,你可以繼續按照這個模式寫下去

    MVC的優點:

  • 耦合性低:視圖層和業務層分離了,如果頁面上顯示改變的話,直接在視圖層更改即可,不用動模型層和控制層上的代碼;也就是視圖層 與 模型層和控制層
  • 已經分離了;所以很容易改變應用層的數據層和業務規則。

  • 可維護性:分離視圖層和業務邏輯層也使得WEB應用更易于維護和修改。
  • MVC的缺點:

    個人覺得適合于大型項目,對于中小型項目并不適合,因為要實現一個簡單的增刪改操作,只需要一點點JS代碼,但是MVC模式代碼量明顯增加了。

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

    參考資料:

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

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

    總結

    以上是生活随笔為你收集整理的javascript 观察者(发布订阅)模式详解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。