亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

理解javascript中的MVC模式

 更新時(shí)間:2016年01月28日 15:19:34   投稿:lijiao  
這篇文章主要為大家介紹了javascript中的MVC模式,MVC是一種軟件架構(gòu)模式,一般把軟件模式分為三部分,本文就針對(duì)MVC模式的三部分進(jìn)行講解,感興趣的小伙伴們可以參考一下

MVC模式是軟件工程中一種軟件架構(gòu)模式,一般把軟件模式分為三部分,模型(Model)+視圖(View)+控制器(Controller);

模型:模型用于封裝與應(yīng)用程序的業(yè)務(wù)邏輯相關(guān)的數(shù)據(jù)以及對(duì)數(shù)據(jù)處理的方法。模型有對(duì)數(shù)據(jù)直接訪問(wèn)的權(quán)利。模型不依賴 “視圖” 和 “控制器”, 也就是說(shuō) 模型它不關(guān)心頁(yè)面如何顯示及如何被操作.

視圖:視圖層最主要的是監(jiān)聽模型層上的數(shù)據(jù)改變,并且實(shí)時(shí)的更新html頁(yè)面。當(dāng)然也包括一些事件的注冊(cè)或者ajax請(qǐng)求操作(發(fā)布事件),都是放在視圖層來(lái)完成。

控制器:控制器接收用戶的操作,最主要是訂閱視圖層的事件,然后調(diào)用模型或視圖去完成用戶的操作;比如:當(dāng)頁(yè)面上觸發(fā)一個(gè)事件,控制器不輸出任何東西及對(duì)頁(yè)面做任何處理; 它只是接收請(qǐng)求并決定調(diào)用模型中的那個(gè)方法去處理請(qǐng)求, 然后再確定調(diào)用那個(gè)視圖中的方法來(lái)顯示返回的數(shù)據(jù)。

下面我們來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的下拉框控件,我們可以對(duì)它進(jìn)行增刪操作;如下圖所示:

代碼如下:

/*
 模型用于封裝與應(yīng)用程序的業(yè)務(wù)邏輯相關(guān)的數(shù)據(jù)以及對(duì)數(shù)據(jù)處理的方法。模型有對(duì)數(shù)據(jù)直接訪問(wèn)的權(quán)利。
 模型不依賴 "視圖" 和 "控制器", 也就是說(shuō) 模型它不關(guān)心頁(yè)面如何顯示及如何被操作.
*/
function Mode(elems) {
  // 所有元素
  this._elems = elems;
 
  // 被選中元素的索引
  this._selectedIndex = -1;
 
  // 增加一項(xiàng)
  this.itemAdd = new Event(this);
 
  // 刪除一項(xiàng)
  this.itemRemoved = new Event(this);
 
  this.selectedIndexChanged = new Event(this);
}
 
Mode.prototype = {
 
  constructor: 'Mode',
 
  // 獲取所有的項(xiàng)
  getItems: function(){
    return [].concat(this._elems);
  },
  // 增加一項(xiàng)
  addItem: function(elem) {
    this._elems.push(elem);
    this.itemAdd.notify({elem:elem});
  },
  // 刪除一項(xiàng)
  removeItem: function(index) {
    var item = this._elems[index];
    this._elems.splice(index,1);
    this.itemRemoved.notify({elem:item});
 
    if(index === this._selectedIndex) {
      this.setSelectedIndex(-1);
    }
  },
  getSelectedIndex: function(){
    return this._selectedIndex;
  },
  setSelectedIndex: function(index){
    var previousIndex = this._selectedIndex;
    this._selectedIndex = index;
    this.selectedIndexChanged.notify({previous : previousIndex});
  }
};
/*
 下面是觀察者模式類,它又叫發(fā)布---訂閱模式;它定義了對(duì)象間的一種一對(duì)多的關(guān)系,
 讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一個(gè)主題對(duì)象,當(dāng)一個(gè)對(duì)象發(fā)生改變時(shí),所有依賴于它的對(duì)象都將得到通知。
*/
function Event(observer) {
  this._observer = observer;
  this._listeners = [];
}
Event.prototype = {
  constaructor: 'Event',
  attach : function(listeners) {
    this._listeners.push(listeners);
  },
  notify: function(objs){
    for(var i = 0,ilen = this._listeners.length; i ) {
      this._listeners[i](this._observer,objs);
    }
  }
};
 
/*
 * 視圖顯示模型數(shù)據(jù),并觸發(fā)UI事件。
 */
function View(model,elements){
  this._model = model;
  this._elements = elements;
 
  this.listModified = new Event(this);
  this.addButtonClicked = new Event(this);
  this.delButtonClicked = new Event(this);
  var that = this;
 
  // 綁定模型監(jiān)聽器
  this._model.itemAdd.attach(function(){
    that.rebuildList();
  });
  this._model.itemRemoved.attach(function(){
    that.rebuildList();
  });
 
  // 將監(jiān)聽器綁定到HTML控件上
  this._elements.list.change(function(e){
    that.listModified.notify({index: e.target.selectedIndex});
  });
  // 添加按鈕綁定事件
  this._elements.addButton.click(function(e){
    that.addButtonClicked.notify();
  });
  // 刪除按鈕綁定事件
  this._elements.delButton.click(function(e){
    that.delButtonClicked.notify();
  });
}
View.prototype = {
  constructor: 'View',
  show: function(){
    this.rebuildList();
  },
  rebuildList: function(){
    var list = this._elements.list,
      items,
      key;
    list.html("");
    items = this._model.getItems();
    for(key in items) {
      if(items.hasOwnProperty(key)) {
        list.append('' +items[key]+ '');
      }
    }
    this._model.setSelectedIndex(-1);
  }
};
/*
 控制器響應(yīng)用戶操作,調(diào)用模型上的變化函數(shù)
 負(fù)責(zé)轉(zhuǎn)發(fā)請(qǐng)求,對(duì)請(qǐng)求進(jìn)行處理
*/
function Controller(model,view) {
  this._model = model;
  this._view = view;
  var that = this;
 
  this._view.listModified.attach(function(sender,args){
    that.updateSelected(args.index);
  });
  this._view.addButtonClicked.attach(function(){
    that.addItem();
  });
  this._view.delButtonClicked.attach(function(){
    that.delItem();
  });
}
Controller.prototype = {
  constructor: 'Controller',
 
  addItem: function(){
    var item = window.prompt('Add item:', '');
    if (item) {
      this._model.addItem(item);
    }
  },
 
  delItem: function(){
    var index = this._model.getSelectedIndex();
    if(index !== -1) {
      this._model.removeItem(index);
    }
  },
 
  updateSelected: function(index){
    this._model.setSelectedIndex(index);
  }
};

HTML代碼如下:

<select id="list" size="10" style="width: 10rem">select>br/>
<button id="plusBtn"> + button>
<button id="minusBtn"> - button>

頁(yè)面初始化代碼如下:

$(function () {
  var model = new Mode(['PHP', 'JavaScript']),
   view = new View(model, {
    'list' : $('#list'), 
    'addButton' : $('#plusBtn'), 
    'delButton' : $('#minusBtn')
    }),
    controller = new Controller(model, view);    
    view.show();
});

代碼分析如下:

  先分析下我們是要實(shí)現(xiàn)什么樣的功能,基本功能有:

一個(gè)下拉框,通過(guò)用戶輸入的操作來(lái)實(shí)現(xiàn)用戶增加一項(xiàng)及用戶選中一項(xiàng)后刪除一項(xiàng)的功能;
當(dāng)然也添加了用戶切換到那一項(xiàng)的事件;

比如我們現(xiàn)在來(lái)增加一條數(shù)據(jù)的時(shí)候,在視圖層上添加監(jiān)聽事件,如下代碼:

// 添加按鈕綁定事件
this._elements.addButton.click(function(e){
  that.addButtonClicked.notify();
});

然后調(diào)用觀察者類Event中的方法notify(發(fā)布一個(gè)事件) that.addButtonClicked.notify();大家都知道,觀察者模式又叫發(fā)布-訂閱模式,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一個(gè)主題對(duì)象,當(dāng)某一個(gè)主題對(duì)象發(fā)生改變的時(shí)候,所有依賴它的對(duì)象都會(huì)得到通知;
因此在控制層(Controller)我們可以使用如下代碼對(duì)發(fā)布者進(jìn)行監(jiān)聽操作:

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

之后調(diào)用自身的方法addItem();代碼如下:

addItem: function(){
  var item = window.prompt('Add item:', '');
  if (item) {
    this._model.addItem(item);
  }
}

調(diào)用模型層(model)的方法addItem();把一條數(shù)據(jù)插入到select框里面去;model(模型層)的addItem()方法代碼如下:

// 增加一項(xiàng)
addItem: function(elem) {
  this._elems.push(elem);
  this.itemAdd.notify({elem:elem});
},

如上代碼 增加一項(xiàng)后,通過(guò) this.itemAdd 發(fā)布一個(gè)消息,然后在視圖層(View)上通過(guò)如下代碼來(lái)監(jiān)聽這個(gè)消息;代碼如下:

// 綁定模型監(jiān)聽器
this._model.itemAdd.attach(function(){
   that.rebuildList();
});

最后監(jiān)聽到模型上(Model)的數(shù)據(jù)發(fā)生改變后,及時(shí)調(diào)用自身的方法rebuildList()去更新頁(yè)面上的數(shù)據(jù);

模型層(Model)最主要做業(yè)務(wù)數(shù)據(jù)封裝操作。視圖層(View)主要發(fā)布事件操作及監(jiān)聽模型層上的數(shù)據(jù),如果模型層上有數(shù)據(jù)改變的時(shí)候,及時(shí)更新頁(yè)面操作,最后顯示給頁(yè)面上來(lái),控制層(Controller)主要監(jiān)聽視圖層(View)的事件,調(diào)用模型層(Model)的方法來(lái)更新模型上的數(shù)據(jù),模型層數(shù)據(jù)更新后,會(huì)發(fā)布一條消息出去,最后視圖層(View)通過(guò)監(jiān)聽模型層(Model)的數(shù)據(jù)變化,來(lái)更新頁(yè)面的顯示; 如上是MVC的基本流程。
MVC的優(yōu)點(diǎn):
        1. 耦合性低:視圖層和業(yè)務(wù)層分離了,如果頁(yè)面上顯示改變的話,直接在視圖層更改即可,不用動(dòng)模型層和控制層上的代碼;也就是視圖層 與 模型層和控制層
已經(jīng)分離了;所以很容易改變應(yīng)用層的數(shù)據(jù)層和業(yè)務(wù)規(guī)則。
        2. 可維護(hù)性:分離視圖層和業(yè)務(wù)邏輯層也使得WEB應(yīng)用更易于維護(hù)和修改。
MVC的缺點(diǎn):
        個(gè)人覺得適合于大型項(xiàng)目,對(duì)于中小型項(xiàng)目并不適合,因?yàn)橐獙?shí)現(xiàn)一個(gè)簡(jiǎn)單的增刪改操作,只需要一點(diǎn)點(diǎn)JS代碼,但是MVC模式代碼量明顯增加了。
對(duì)于學(xué)習(xí)成本也就提高了,當(dāng)然如果使用一些封裝好的MVC庫(kù)或者框架就好了。

以上就是關(guān)于javascript中的MVC模式實(shí)現(xiàn)方法,優(yōu)缺點(diǎn)的詳細(xì)分析,希望對(duì)大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • JS基于構(gòu)造函數(shù)實(shí)現(xiàn)的菜單滑動(dòng)顯隱效果【測(cè)試可用】

    JS基于構(gòu)造函數(shù)實(shí)現(xiàn)的菜單滑動(dòng)顯隱效果【測(cè)試可用】

    這篇文章主要介紹了JS基于構(gòu)造函數(shù)實(shí)現(xiàn)的菜單滑動(dòng)顯隱效果,可實(shí)現(xiàn)基本的菜單折疊與展開功能,涉及javascript響應(yīng)鼠標(biāo)事件動(dòng)態(tài)操作頁(yè)面元素的相關(guān)技巧,需要的朋友可以參考下
    2016-06-06
  • JavaScript實(shí)現(xiàn)雪花飄落效果

    JavaScript實(shí)現(xiàn)雪花飄落效果

    這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)雪花飄落效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • 動(dòng)態(tài)加載js、css的實(shí)例代碼

    動(dòng)態(tài)加載js、css的實(shí)例代碼

    這篇文章主要介紹了動(dòng)態(tài)加載js、css的實(shí)例代碼的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,感興趣的朋友一起看看吧
    2016-05-05
  • JS定時(shí)器不可靠的原因及解決方案

    JS定時(shí)器不可靠的原因及解決方案

    JavaScript中所有的任務(wù)分為同步任務(wù)與異步任務(wù),同步任務(wù),顧名思義就是立即執(zhí)行的任務(wù),它一般是直接進(jìn)入到主線程中執(zhí)行,這篇文章主要介紹了JS定時(shí)器不可靠的原因及解決方案,需要的朋友可以參考下
    2022-01-01
  • 最新評(píng)論