99re热视频这里只精品,久久久天堂国产精品女人,国产av一区二区三区,久久久精品成人免费看片,99久久精品免费看国产一区二区三区

MVC框架與Backbone.js

2021-09-15 16:17 更新

MVC框架

隨著JavaScript程序變得越來(lái)越復(fù)雜,往往需要一個(gè)團(tuán)隊(duì)協(xié)作開(kāi)發(fā),這時(shí)代碼的模塊化和組織規(guī)范就變得異常重要了。MVC模式就是代碼組織的經(jīng)典模式。

(……MVC介紹。)

(1)Model

Model表示數(shù)據(jù)層,也就是程序需要的數(shù)據(jù)源,通常使用JSON格式表示。

(2)View

View表示表現(xiàn)層,也就是用戶界面,對(duì)于網(wǎng)頁(yè)來(lái)說(shuō),就是用戶看到的網(wǎng)頁(yè)HTML代碼。

(3)Controller

Controller表示控制層,用來(lái)對(duì)原始數(shù)據(jù)(Model)進(jìn)行加工,傳送到View。

由于網(wǎng)頁(yè)編程不同于客戶端編程,在MVC的基礎(chǔ)上,JavaScript社區(qū)產(chǎn)生了各種變體框架MVP(Model-View-Presenter)、MVVM(Model-View-ViewModel)等等,有人就把所有這一類(lèi)框架的各種模式統(tǒng)稱(chēng)為MV*。

框架的優(yōu)點(diǎn)在于合理組織代碼、便于團(tuán)隊(duì)合作和未來(lái)的維護(hù),缺點(diǎn)在于有一定的學(xué)習(xí)成本,且限制你只能采取它的寫(xiě)法。

零框架解決方案

MVC框架(尤其是大型框架)有一個(gè)嚴(yán)重的缺點(diǎn),就是會(huì)產(chǎn)生用戶的重度依賴(lài)。一旦框架本身出現(xiàn)問(wèn)題或者停止更新,用戶的處境就會(huì)很困難,維護(hù)和更新成本極高。

ES6的到來(lái),使得JavaScript語(yǔ)言有了原生的模塊解決方案。于是,開(kāi)發(fā)者有了另一種選擇,就是不使用MVC框架,只使用各種單一用途的模塊庫(kù),組合完成一個(gè)項(xiàng)目。下面是可供選擇的各種用途的模塊列表。

輔助功能庫(kù)(Helper Libraries)

路由庫(kù)(Routing)

  • router.js:Ember.js使用的路由庫(kù)
  • route-recognizer:功能全面的路由庫(kù)
  • page.js:類(lèi)似Express路由的庫(kù)
  • director:同時(shí)支持服務(wù)器和瀏覽器的路由庫(kù)

Promise庫(kù)

  • RSVP.js:ES6兼容的Promise庫(kù)
  • ES6-Promise:RSVP.js的子集,但是全面兼容ES6
  • q:最常用的Promise庫(kù)之一,AngularJS用了它的精簡(jiǎn)版
  • native-promise-only:嚴(yán)格符合ES6的Promise標(biāo)準(zhǔn),同時(shí)兼容老式瀏覽器

客戶端與服務(wù)器的通信庫(kù)

  • fetch:實(shí)現(xiàn)window.fetch功能
  • qwest:支持XHR2和Promise的Ajax庫(kù)
  • jQuery:jQuery 2.0支持按模塊打包,因此可以創(chuàng)建一個(gè)純Ajax功能庫(kù)

動(dòng)畫(huà)庫(kù)(Animation)

  • cssanimevent:兼容老式瀏覽器的CSS3動(dòng)畫(huà)庫(kù)
  • Velocity.js:性能優(yōu)秀的動(dòng)畫(huà)庫(kù)

輔助開(kāi)發(fā)庫(kù)(Development Assistance)

  • LogJS:輕量級(jí)的logging功能庫(kù)
  • UserTiming.js:支持老式瀏覽器的高精度時(shí)間戳庫(kù)

流程控制和架構(gòu)(Flow Control/Architecture)

數(shù)據(jù)綁定(Data-binding)

  • Object.observe():Chrome已經(jīng)支持該方法,可以輕易實(shí)現(xiàn)雙向數(shù)據(jù)綁定

模板庫(kù)(Templating)

  • Mustache:大概是目前使用最廣的不含邏輯的模板系統(tǒng)

微框架(Micro-Framework)

某些情況下,可以使用微型框架,作為項(xiàng)目開(kāi)發(fā)的起點(diǎn)。

  • bottlejs:提供惰性加載、中間件鉤子、裝飾器等功能
  • Stapes.js:微型MVC框架
  • soma.js:提供一個(gè)松耦合、易測(cè)試的架構(gòu)
  • knockout:最流行的微框架之一,主要關(guān)注UI

Backbone的加載

<script src="https://atts.w3cschool.cn/attachments/image/cimg/jquery.js"></script>
<script src="https://atts.w3cschool.cn/attachments/image/cimg/underscore.js"></script>
<script src="https://atts.w3cschool.cn/attachments/image/cimg/backbone.js"></script>
<script src="https://atts.w3cschool.cn/attachments/image/cimg/jst.js"></script>

<script src="https://atts.w3cschool.cn/attachments/image/cimg/router.js"></script>
<script src="https://atts.w3cschool.cn/attachments/image/cimg/init.js"></script>

Backbone的用法

Backbone是最早的JavaScript MVC框架,也是最簡(jiǎn)化的一個(gè)框架。它的設(shè)計(jì)思想是,只提供最基本的功能,給用戶提供最大的自由。這意味著,好的一面是它沒(méi)有一整套規(guī)則,強(qiáng)制你接受,壞的一面是很多功能你必須自己實(shí)現(xiàn)。Backbone的體積相當(dāng)小,最小化后只有30多KB。

定義一個(gè)對(duì)象,表示W(wǎng)eb應(yīng)用。

var AppName = {
  Models       :{},
  Views        :{},
  Collections  :{},
  Controllers  :{}
};

上面代碼表示,應(yīng)用由四部分組成:Model、Collection、Controller和View。

定義Model,表示數(shù)據(jù)的一個(gè)基本單位。

AppName.Models.Person = Backbone.Model.extend({
  urlRoot: "/persons"
});

定義Collection,表示Model的集合。

AppName.Collections.Library = Backbone.Collection.extend({
  model: AppName.Models.Book
});

上面代碼表示,Collection對(duì)象必須有model屬性,指明由哪一個(gè)model構(gòu)成。

定義一個(gè)View。

AppName.Views.Modals.AcceptDecline = Backbone.View.Extend({
  el: ".modal-accept",

  events: {
    "ajax:success .link-accept" :"acceptSuccess",
    "ajax:error   .link-accept" :"acceptError"
  },

  acceptSuccess :function(evt, response) {
    this.$el.modal("hide");
    alert('Cool! Thanks');
  },

  acceptError :function(evt, response) {
    var $modalContent = this.$el.find('.panel-modal');

    $modalContent.append("Something was wrong!");
  }
});

View對(duì)象必須有el屬性,指明當(dāng)前View綁定的DOM節(jié)點(diǎn),events屬性指明事件和對(duì)應(yīng)的方法。

定義一個(gè)Controller。

AppName.Controllers.Person = {};
AppName.Controllers.Person.show = function(id) {
  var aMa = new AppName.Models.Person({id: id});

  aMa.updateAge(25);

  aMa.fetch().done(function(){
    var view = new AppName.Views.Show({model: aMa});
  });
};

最后,定義路由,啟動(dòng)應(yīng)用程序。

var Workspace = Backbone.Router.extend({
  routes: {
    "*"                  :"wholeApp",
    "users/:id"          :"usersShow",
    "users/:id/orders/"  :"ordersIndex"
  },

  wholeApp    :AppName.Controller.Application.default,
  usersShow   :AppName.Controller.Users.show,
  ordersIndex :AppName.Controller.Orders.index
});

new Workspace();
Backbone.history.start({pushState: true});

Backbone.View

基本用法

Backbone.View方法用于定義視圖類(lèi)。

var AppView = Backbone.View.extend({
  render: function(){
    $('main').append('<h1>一級(jí)標(biāo)題</h1>');
  }
});

上面代碼通過(guò)Backbone.View的extend方法,定義了一個(gè)視圖類(lèi)AppView。該類(lèi)內(nèi)部有一個(gè)render方法,用于將視圖放置在網(wǎng)頁(yè)上。

使用的時(shí)候,需要先新建視圖類(lèi)的實(shí)例,然后通過(guò)實(shí)例,調(diào)用render方法,從而讓視圖在網(wǎng)頁(yè)上顯示。

var appView = new AppView();
appView.render();

上面代碼新建視圖類(lèi)AppView的實(shí)例appView,然后調(diào)用appView.render,網(wǎng)頁(yè)上就會(huì)顯示指定的內(nèi)容。

新建視圖實(shí)例時(shí),通常需要指定Model。

var document = new Document({
  model: doc
});

initialize方法

視圖還可以定義initialize方法,生成實(shí)例的時(shí)候,會(huì)自動(dòng)調(diào)用該方法對(duì)實(shí)例初始化。

var AppView = Backbone.View.extend({
  initialize: function(){
    this.render();
  },
  render: function(){
    $('main').append('<h1>一級(jí)標(biāo)題</h1>');
  }
});

var appView = new AppView();

上面代碼定義了initialize方法之后,就省去了生成實(shí)例后,手動(dòng)調(diào)用appView.render()的步驟。

el屬性,$el屬性

除了直接在render方法中,指定“視圖”所綁定的網(wǎng)頁(yè)元素,還可以用視圖的el屬性指定網(wǎng)頁(yè)元素。

var AppView = Backbone.View.extend({
  el: $('main'),
  render: function(){
    this.$el.append('<h1>一級(jí)標(biāo)題</h1>');
  }
});

上面的代碼與render方法直接綁定網(wǎng)頁(yè)元素,效果完全一樣。上面代碼中,除了el屬性,還是$el屬性,前者代表指定的DOM元素,后者則表示該DOM元素對(duì)應(yīng)的jQuery對(duì)象。

tagName屬性,className屬性

如果不指定el屬性,也可以通過(guò)tagName屬性和className屬性指定。

var Document = Backbone.View.extend({
  tagName: "li",
  className: "document",
  render: function() {
   // ...
  }
});

template方法

視圖的template屬性用來(lái)指定網(wǎng)頁(yè)模板。

var AppView = Backbone.View.extend({
      template: _.template("<h3>Hello <%= who %><h3>"),
});

上面代碼中,underscore函數(shù)庫(kù)的template函數(shù),接受一個(gè)模板字符串作為參數(shù),返回對(duì)應(yīng)的模板函數(shù)。有了這個(gè)模板函數(shù),只要提供具體的值,就能生成網(wǎng)頁(yè)代碼。

var AppView = Backbone.View.extend({
      el: $('#container'),
      template: _.template("<h3>Hello <%= who %><h3>"),
      initialize: function(){
        this.render();
      },
      render: function(){
        this.$el.html(this.template({who: 'world!'}));
      }
});

上面代碼的render就調(diào)用了template方法,從而生成具體的網(wǎng)頁(yè)代碼。

實(shí)際應(yīng)用中,一般將模板放在script標(biāo)簽中,為了防止瀏覽器按照J(rèn)avaScript代碼解析,type屬性設(shè)為text/template。

<script type="text/template" data-name="templateName">
    <!-- template contents goes here -->
</script>

可以使用下面的代碼編譯模板。

window.templates = {};

var $sources = $('script[type="text/template"]');

$sources.each(function(index, el) {
    var $el = $(el);
    templates[$el.data('name')] = _.template($el.html());
});

events屬性

events屬性用于指定視圖的事件及其對(duì)應(yīng)的處理函數(shù)。

var Document = Backbone.View.extend({
  events: {
    "click .icon":          "open",
    "click .button.edit":   "openEditDialog",
    "click .button.delete": "destroy"
  }
});

上面代碼中一個(gè)指定了三個(gè)CSS選擇器的單擊事件,及其對(duì)應(yīng)的三個(gè)處理函數(shù)。

listento方法

listento方法用于為特定事件指定回調(diào)函數(shù)。

var Document = Backbone.View.extend({
  initialize: function() {
    this.listenTo(this.model, "change", this.render);
  }
});

上面代碼為model的change事件,指定了回調(diào)函數(shù)為render。

remove方法

remove方法用于移除一個(gè)視圖。

updateView: function() {
  view.remove();
  view.render();
};

子視圖(subview)

在父視圖中可以調(diào)用子視圖。下面就是一種寫(xiě)法。

render : function (){

    this.$el.html(this.template());

    this.child = new Child();

    this.child.appendTo($.('.container-placeholder').render();
}

Backbone.Router

Router是Backbone提供的路由對(duì)象,用來(lái)將用戶請(qǐng)求的網(wǎng)址與后端的處理函數(shù)一一對(duì)應(yīng)。

首先,新定義一個(gè)Router類(lèi)。

Router = Backbone.Router.extend({
    routes: {
    }
});

routes屬性

Backbone.Router對(duì)象中,最重要的就是routes屬性。它用來(lái)設(shè)置路徑的處理方法。

routes屬性是一個(gè)對(duì)象,它的每個(gè)成員就代表一個(gè)路徑處理規(guī)則,鍵名為路徑規(guī)則,鍵值為處理方法。

如果鍵名為空字符串,就代表根路徑。

routes: {
        '': 'phonesIndex',
},

phonesIndex: function () {
        new PhonesIndexView({ el: 'section#main' });
}

星號(hào)代表任意路徑,可以設(shè)置路徑參數(shù),捕獲具體的路徑值。

var AppRouter = Backbone.Router.extend({
    routes: {
        "*actions": "defaultRoute" 
    }
});

var app_router = new AppRouter;

app_router.on('route:defaultRoute', function(actions) {
    console.log(actions);
})

上面代碼中,根路徑后面的參數(shù),都會(huì)被捕獲,傳入回調(diào)函數(shù)。

路徑規(guī)則的寫(xiě)法。

var myrouter = Backbone.Router.extend({
  routes: {
    "help":                 "help",    
    "search/:query":        "search" 
  },

  help: function() {
    ...
  },

  search: function(query) {
    ...
  }
});

routes: {
  "help/:page":         "help",
  "download/*path":     "download",
  "folder/:name":       "openFolder",
  "folder/:name-:mode": "openFolder"
}
router.on("route:help", function(page) {
  ...
});

Backbone.history

設(shè)置了router以后,就可以啟動(dòng)應(yīng)用程序。Backbone.history對(duì)象用來(lái)監(jiān)控url的變化。

App = new Router();

$(document).ready(function () {
    Backbone.history.start({ pushState: true });
});

打開(kāi)pushState方法。如果應(yīng)用程序不在根目錄,就需要指定根目錄。

Backbone.history.start({pushState: true, root: "/public/search/"})

Backbone.Model

Model代表單個(gè)的對(duì)象實(shí)體。

var User = Backbone.Model.extend({
        defaults: {
            name: '',
            email: ''
        }
});

var user = new User();

上面代碼使用extend方法,生成了一個(gè)User類(lèi),它代表model的模板。然后,使用new命令,生成一個(gè)Model的實(shí)例。defaults屬性用來(lái)設(shè)置默認(rèn)屬性,上面代碼表示user對(duì)象默認(rèn)有name和email兩個(gè)屬性,它們的值都等于空字符串。

生成實(shí)例時(shí),可以提供各個(gè)屬性的具體值。

var user = new User ({
    id: 1,
    name: 'name',
    email: 'name@email.com'
});

上面代碼在生成實(shí)例時(shí),提供了各個(gè)屬性的具體值。

idAttribute屬性

Model實(shí)例必須有一個(gè)屬性,作為區(qū)分其他實(shí)例的主鍵。這個(gè)屬性的名稱(chēng),由idAttribute屬性設(shè)定,一般是設(shè)為id。

var Music = Backbone.Model.extend({ 
    idAttribute: 'id'
});

get方法

get方法用于返回Model實(shí)例的某個(gè)屬性的值。

var user = new User({ name: "name", age: 24});
var age = user.get("age"); // 24
var name = user.get("name"); // "name"

set方法

set方法用于設(shè)置Model實(shí)例的某個(gè)屬性的值。

var User = Backbone.Model.extend({
    buy: function(newCarsName){
        this.set({car: newCarsName });
    }
});

var user = new User({name: 'BMW',model:'i8',type:'car'});
user.buy('Porsche');
var car = user.get("car"); // ‘Porsche’

on方法

on方法用于監(jiān)聽(tīng)對(duì)象的變化。

var user = new User({name: 'BMW',model:'i8'});

user.on("change:name", function(model){
    var name = model.get("name"); // "Porsche"
    console.log("Changed my car’s name to " + name);
});

user.set({name: 'Porsche'}); 
// Changed my car’s name to Porsche

上面代碼中的on方法用于監(jiān)聽(tīng)事件,“change:name”表示name屬性發(fā)生變化。

urlroot屬性

該屬性用于指定服務(wù)器端對(duì)model進(jìn)行操作的路徑。

var User = Backbone.Model.extend({
    urlRoot: '/user'
});

上面代碼指定,服務(wù)器對(duì)應(yīng)該Model的路徑為/user。

fetch事件

fetch事件用于從服務(wù)器取出Model。

var user = new User ({id: 1});
user.fetch({
    success: function (user){
        console.log(user.toJSON());
    }
})

上面代碼中,user實(shí)例含有id屬性(值為1),fetch方法使用HTTP動(dòng)詞GET,向網(wǎng)址“/user/1”發(fā)出請(qǐng)求,從服務(wù)器取出該實(shí)例。

save方法

save方法用于通知服務(wù)器新建或更新Model。

如果一個(gè)Model實(shí)例不含有id屬性,則save方法將使用POST方法新建該實(shí)例。

var User = Backbone.Model.extend({
    urlRoot: '/user'
});

var user = new User ();
var userDetails = {
    name: 'name',
    email: 'name@email.com'
};

user.save(userDetails, {
    success: function (user) {
        console.log(user.toJSON());
    }
})

上面代碼先在類(lèi)中指定Model對(duì)應(yīng)的網(wǎng)址是/user,然后新建一個(gè)實(shí)例,最后調(diào)用save方法。它有兩個(gè)參數(shù),第一個(gè)是實(shí)例對(duì)象的具體屬性,第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù)對(duì)象,設(shè)定success事件(保存成功)的回調(diào)函數(shù)。具體來(lái)說(shuō),save方法會(huì)向/user發(fā)出一個(gè)POST請(qǐng)求,并將{name: 'name', email: 'name@email.com'}作為數(shù)據(jù)提供。

如果一個(gè)Model實(shí)例含有id屬性,則save方法將使用PUT方法更新該實(shí)例。

var user = new User ({
    id: 1,
    name: '張三',
    email: 'name@email.com'
});

user.save({name: '李四'}, {
    success: function (model) {
        console.log(user.toJSON());
    }
}); 

上面代碼中,對(duì)象實(shí)例含有id屬性(值為1),save將使用PUT方法向網(wǎng)址“/user/1”發(fā)出請(qǐng)求,從而更新該實(shí)例。

destroy方法

destroy方法用于在服務(wù)器上刪除該實(shí)例。

var user = new User ({
    id: 1,
    name: 'name',
    email: 'name@email.com'
});

user.destroy({
    success: function () {
       console.log('Destroyed');
    }
});

上面代碼的destroy方法,將使用HTTP動(dòng)詞DELETE,向網(wǎng)址“/user/1”發(fā)出請(qǐng)求,刪除對(duì)應(yīng)的Model實(shí)例。

Backbone.Collection

Collection是同一類(lèi)Model的集合,比如Model是動(dòng)物,Collection就是動(dòng)物園;Model是單個(gè)的人,Collection就是一家公司。

var Song = Backbone.Model.extend({});

var Album = Backbone.Collection.extend({
    model: Song
});

上面代碼中,Song是Model,Album是Collection,而且Album有一個(gè)model屬性等于Song,因此表明Album是Song的集合。

add方法,remove方法

Model的實(shí)例可以直接放入Collection的實(shí)例,也可以用add方法添加。

var song1 = new Song({ id: 1 ,name: "歌名1", artist: "張三" });
var song2 = new Music ({id: 2,name: "歌名2", artist: "李四" });
var myAlbum = new Album([song1, song2]);

var song3 = new Music({ id: 3, name: "歌名3",artist:"趙五" });
myAlbum.add(song3);

remove方法用于從Collection實(shí)例中移除一個(gè)Model實(shí)例。

myAlbum.remove(1);

上面代碼表明,remove方法的參數(shù)是model實(shí)例的id屬性。

get方法,set方法

get方法用于從Collection中獲取指定id的Model實(shí)例。

myAlbum.get(2))

fetch方法

fetch方法用于從服務(wù)器取出Collection數(shù)據(jù)。

var songs = new Backbone.Collection;
songs.url = '/songs';
songs.fetch();

Backbone.events

var obj = {};
_.extend(obj, Backbone.Events);

obj.on("show-message", function(msg) {
    $('#display').text(msg);
});

obj.trigger("show-message", "Hello World");

參考鏈接

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)