中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

backbone簡介_動力節點Java學院整理

發布時間:2020-10-13 17:56:48 來源:腳本之家 閱讀:202 作者:Armeli-Battana 欄目:web開發

簡介

Web 應用程序越來越關注于前端,使用客戶端腳本與 Ajax 進行交互。由于 JavaScript 應用程序越來越復雜,如果沒有合適的工具和模式,那么 JavaScript 代碼的高效編寫、非重復性和可維護性方面會面臨挑戰。模型-視圖-控制器 (MVC) 是一個常見模式,可用于服務器端開發以生成有組織以及易維護的代碼。MVC 支持將數據(比如通常用于 Ajax 交互的 JavaScript Object Notation (JSON) 對象)從表示層或從頁面的文檔對象模型 (document object model, DOM) 中分離出來,也可適用于客戶端開發。

Backbone(也稱為 Backbone.js)是由 Jeremy Ashkenas 創建的一個輕量級庫,可用于創建 MVC 類應用程序。Backbone:

  1. 強制依賴于 Underscore.js,Underscore.js 是一個實用型庫
  2. 非強制依賴于 jQuery/Zepto
  3. 根據模型的變更自動更新應用程序的 HTML,有助于代碼維護
  4. 促進客戶端模板使用,避免了在 JavaScript 中嵌入 HTML 代碼

模型、視圖、集合和路由器是 Backbone 框架中的主要組件。在 Backbone 中,模型會存儲通過 RESTful JSON 接口從服務器檢索到的數據。模型與視圖密切關聯,負責為特定 UI 組件渲染 HTML 并處理元素上觸發的事件,這也是視圖本身的一部分。

SPI 應用程序:Backbone.Router 和 Backbone.history

含有大量 Ajax 交互的應用程序越來越像那些無頁面刷新的應用程序。這些應用程序常常試圖限制與單個頁面的交互。該 SPI 方法提高了效率和速度,并使整個應用程序變得更靈敏。狀態概念代替了頁面概念。散列 (Hash) 片段被用于識別一個特定狀態。散列片段 是 URL 中散列標簽 (#) 后的那部分,是該類應用程序的關鍵元素。清單 1 顯示了一個 SPI 應用程序使用兩個不同的散列片段產生的兩個不同狀態。

清單 1. SPI 或 Ajax 應用程序中的兩個不同狀態

http://www.example.com/#/state1

http://www.example.com/#/state2

Backbone 提供一個稱為路由器(版本 0.5 前稱之為控制器)的組件來路由客戶端狀態。路由器可以擴展 Backbone.Router 函數,且包含一個散列映射(routes 屬性)將狀態與活動關聯起來。當應用程序達到相關狀態時,會觸發一個特定活動。清單2 展示了一個 Backbone 路由器示例。

清單 2. Backbone.Router 示例:routers.js

App.Routers.Main = Backbone.Router.extend({
  
  // Hash maps for routes
  routes : {
   "" : "index",
   "/teams" : "getTeams",
   "/teams/:country" : "getTeamsCountry",
   "/teams/:country/:name : "getTeam"
   "*error" : "fourOfour"
  },
  
  index: function(){
    // Homepage 
  },
  
  getTeams: function() {
    // List all teams 
  },
  getTeamsCountry: function(country) {
    // Get list of teams for specific country
  },
  getTeam: function(country, name) {
    // Get the teams for a specific country and with a specific name
  }, 
  fourOfour: function(error) {
    // 404 page
  }
});

創建的每個狀態可以為書簽。當 URL 碰到類似下面情況時,會調用這 5 個活動(index、getTeams、getTeamsCountry、getTeamCountry 和 fourOfour)。

  1. http://www.example.com 觸發 index()
  2. http://www.example.com/#/teams 觸發 getTeams()
  3. http://www.example.com/#/teams/country1 觸發 getTeamsCountry() 傳遞 country1 作為參數
  4. http://www.example.com/#/teams/country1/team1 觸發 getTeamCountry() 傳遞 country1 和 team1 作為參數
  5. http://www.example.com/#/something 觸發 fourOfour() 以作 * (星號)使用。

要啟動 Backbone,先實例化頁面加載的路由器,并通過指令 Backbone.history.start() 方法監視散列片段中的任何變更,如 清單 3 所示。

清單 3. 應用程序實例化(使用 jQuery)

$(function(){
  var router = new App.Routers.Main();
  Backbone.history.start({pushState : true});
})

當實例化路由器時,會生成 Backbone.history 對象;它將自動引用 Backbone.History 函數。Backbone.History 負責匹配路由和router 對象中定義的活動。start() 方法觸發后,將創建 Backbone.history 的 fragment 屬性。它包含散列片段的值。該序列在根據狀態次序管理瀏覽器歷史方面十分有用。用戶如果想要返回前一狀態,單擊瀏覽器的返回按鈕。

在 清單 3 的示例中,通過一個啟用 HTML5 特性 pushState 的配置調用 start() 方法。對于那些支持 pushState 的瀏覽器,Backbone 將監視 popstate 事件以觸發一個新狀態。如果瀏覽器不能支持 HTML5 特性,那么 onhashchange 活動會被監視。如果瀏覽器不支持該事件,輪詢技術將監視 URL 散列片段的任何更改。

模型和集合

模型和集合是 Backbone.js 的重要組件,模型將數據(通常是來自服務器的數據)存儲在鍵值對中。要創建一個模型,需要擴展Backbone.Model,如 清單 4 所示。

清單 4. Backbone.Model 創建

App.Models.Team = Backbone.Model.extend({
  defaults : {
    // default attributes
  }
  // Domain-specific methods go here
});

App.Models.Team 函數是一個新模型函數,但是必須創建一個實例才能在應用程序中使用特定模型,如 清單 5 所示。

清單 5. 模型實例化

var team1 = new App.Models.Team();

現在,變量 team1 有一個名為 cid 的字段名,這是一個客戶端標識符,形式為 "c" 再加上一個數字(例如,c0、c1、c2)。模型是通過存儲在散列映射中的屬性來定義的。屬性可以在實例化時進行設置,或者使用 set() 方法設置。屬性值可通過 get() 方法檢索。清單 6 顯示了如何通過實例化或 get()/set() 方法設置和獲取屬性。

清單 6. 模型實例化和 get/set 方法

// "name" attribute is set into the model
var team1 = new App.Models.Team({
  name : "name1"
});
console.log(team1.get("name")); // prints "name1"

// "name" attribute is set with a new value
team1.set({
  name : "name2"
});
console.log(team1.get("name")); //prints "name2"

當使用 JavaScript 對象時,使用 set() 方法創建或者設置屬性值的原因并不是顯而易見的。其中一個原因是為了更新此值,如 清單 7 所示。

清單 7. 以錯誤的方法更新屬性

team1.attributes.name = "name2";

為了避免 使用 清單 7 中的代碼,使用 set() 是改變模型狀態并觸發其變更事件的唯一方法。使用 set() 提升封裝原則。清單 8 展示了如何將一個事件處理程序綁到發生變更的事件中。該事件處理程序包含一個 alert,在調用 set() 方法時會被觸發,如 清單 6 所示。但是,在使用 清單 7 中的代碼時不觸發 alert。

清單 8. 更改 App.Models.Team 模型中的事件處理程序

App.Models.Team = Backbone.Model.extend({
  initialize : function(){
    this.bind("change", this.changed);
  },
  changed : function(){
    alert("changed");
  }
});

Backbone 的另一個優勢是易于通過 Ajax 交互與服務器進行通信。在模型上調用一個 save() 方法會通過 REST JSON API 異步將當前狀態保存到服務器。清單 9 展示了此示例。

清單 9. 在模型對象上調用 save 方法

barca.save();

save() 函數將在后臺委托給 Backbone.sync,這是負責發出 RESTful 請求的組件,默認使用 jQuery 函數 $.ajax()。由于調用了 REST 風格架構,每個 Create、Read、Update 或 Delete (CRUD) 活動均會與各種不同類型的 HTTP 請求(POST、GET、PUT 和 DELETE)相關聯。首先保存模型對象,使用一個 POST 請求,創建一個標識符 ID,其后,嘗試發送對象到服務器,使用一個 PUT 請求。

當需要從服務器檢索一個模型時,請求一個 Read 活動并使用一個 Ajax GET 請求。這類請求使用 fetch() 方法。要確定導入模型數據或者從中取出模型數據的服務器的位置:

  1. 如果模型屬于一個 collection,那么集合對象的 url 屬性將是該位置的基礎,并且該模型 ID(不是 cid)會被附加以構成完整的 URL。
  2. 如果模型不是在一個集合中,那么該模型的 urlroot 屬性被用作該位置的基礎

清單 10 顯示了如何獲取一個模型。

清單 10. 模型對象的 Fetch() 方法

var teamNew = new App.Models.Team({
  urlRoot : '/specialTeams'
});
teamNew.save(); // returns model's ID equal to '222'
teamNew.fetch(); // Ajax request to '/specialTeams/222'

validate() 方法被用于驗證模型,如 清單 11 所示。需要重寫 validate() 方法(在調用 set() 方法時觸發)來包含模型的有效邏輯。傳遞給該函數的惟一參數是一個 JavaScript 對象,該對象包含了 set() 方法更新的屬性,以便驗證那些屬性的條件。如果從 validate() 方法中沒有返回任何內容,那么驗證成功。如果返回一個錯誤消息,那么驗證失敗,將無法執行 set() 方法。

清單 11. 模型的驗證方法

App.Models.Team = Backbone.Model.extend({
  validate : function(attributes){
    if (!!attributes && attributes.name === "teamX") {
      // Error message returned if the value of the "name" 
      // attribute is equal to "teamX"
      return "Error!";
    }
  }
}

一組模型被分組到到集合中,這個集合是 Backbone.Collection 的擴展函數。集合具有一個模型屬性的特性,定義了組成該集合的模型類型。使用 add()/remove() 方法可以將一個模型添加和移動到集合中。清單 12 顯示了如何創建和填充一個集合。

清單 12. Backbone 集合

App.Collections.Teams = Backbone.Collection.extend({
  model : App.Models.Team
});
var teams = new App.Collections.Teams();

// Add e model to the collection object "teams"
teams.add(team1);
teams.add(new App.Models.Team({
  name : "Team B"
}));
teams.add(new App.Models.Team());
teams.remove(team1);

console.log(teams.length) // prints 2

創建的 teams 集合中包含一個含有兩個模型的陣列,存儲在模型屬性中。盡管,在典型 Ajax 應用程序中,會從服務器動態(不是人工)填充該集合。fetch() 方法可以幫助完成此項任務,如 清單 13 所示,并將數據存儲到模型陣列中。

清單 13. Fetch() 方法

teams.fetch();

Backbone 中的集合擁有一個 url 屬性,定義了使用 Ajax GET 請求從服務器取出 JSON 數據的位置,如 清單 14 所示。

清單 14. 集合的 url 屬性和 fetch() 方法

teams.url = '/getTeams';
teams.fetch(); //Ajax GET Request to '/getTeams'

Fetch() 方法屬于異步調用,因此,在等待服務器響應時,應用程序不會中止。在一些情況下,要操作來自服務器的原始數據,可以使用集合的 parse() 方法。正如 清單 15 所示。

清單 15. parse() 方法

App.Collections.Teams = Backbone.Collection.extend({
  model : App.Models.Team,
  parse : function(data) {
    // 'data' contains the raw JSON object
    console.log(data);
  }
});

集合提供的另一個有趣的方法是 reset(),它允許將多個模型設置到一個集合中。reset() 方法可以非常方便地將數據引導到集合中,比如頁面加載,來避免用戶等待異步調用返回。

視圖和客戶端模板

Backbone 中的視圖與典型 MVC 方法的視圖不一樣。Backbone 視圖可以擴展 Backbone.View 函數并顯示模型中存儲的數據。一個視圖提供一個由 el 屬性定義的 HTML 元素。該屬性可以是由 tagName、className 和 id 屬性相組合而構成的,或者是通過其本身的 el 值形成的。清單 16 顯示了使用這不同方法組合 el 屬性的兩個不同視圖。

清單 16. Backbone 視圖樣例

// In the following view, el value is 'UL.team-element'
App.Views.Teams = Backbone.View.extend({
  el : 'UL.team-list'
});
// In the following view, el value is 'div.team-element'
App.Views.Team = Backbone.View.extend({
  className : '.team-element',
  tagName : 'div'
});

如果 el、tagName、className 和 id 屬性為空,那么會默認將一個空的 DIV 分配給 el。

如上所述,一個視圖必須與一個模型相關聯。該模型屬性也很有用,如 清單 17 所示。App.View.Team 視圖被綁定到一個App.Models.Team 模型實例。

清單 17. Backbone 視圖中的模型屬性

// In the following view, el value is 'UL.team-element'
App.Views.Team = Backbone.View.extend({
  ...
  model : new App.Models.Team
});

要渲染數據(這是視圖的主要目的),重寫 render() 方法和邏輯來顯示 DOM 元素(由 el 屬性引用的)中的模型屬性。清單 18 展示了一個 render 方法如何更新用戶界面的樣例。

清單 18. Render() 方法

App.Views.Team = Backbone.View.extend({
  className : '.team-element',
  tagName : 'div',
  model : new App.Models.Team
  render : function() {
    // Render the 'name' attribute of the model associated
    // inside the DOM element referred by 'el'
    $(this.el).html("<span>" + this.model.get("name") + "</span>");
  }
});

Backbone 也可以促進客戶端模板的使用,這就使得我們沒有必要在 JavaScript 中嵌入 HTML 代碼,如 清單 18 所示。(使用模板,模板會封裝視圖中常見函數;只指定此函數一次即可。)Backbone 在 underscore.js(一個必須的庫)中提供一個模板引擎,盡管沒有必要使用該模板引擎。清單 19 中的實例使用 underscore.js HTML 模板。

清單 19. HTML 含有模板

<script id="teamTemplate" type="text/template">
  <%= name %>
</script>

清單 20 顯示了另一個使用 underscore.js HTML 模板的樣例。

清單 20. 使用 _.template() 函數的視圖

App.Views.Team = Backbone.View.extend({
  className : '.team-element',
  tagName : 'div',
  model : new App.Models.Team
  render : function() {
    // Compile the template
    var compiledTemplate = _.template($('#teamTemplate').html());
    // Model attributes loaded into the template. Template is
    // appended to the DOM element referred by the el attribute
    $(this.el).html(compiledTemplate(this.model.toJSON()));
  }
});

Backbone 中最有用且最有趣的一個功能是將 render() 方法綁定到模型的變更事件中,如 清單 21 所示。

清單 21. Render() 方法綁定到模型變更事件

// In the following view, el value is 'div.team-element'
App.Views.Team = Backbone.View.extend({
  model : new App.Models.Team,
  initialize : function() {
    this.model.bind("change", this.render, this);
  } 
})

上述代碼將 render() 方法綁定到一個模型的變更事件中。當模型發生更改時,會自動觸發 render() 方法,從而節省數行代碼。從 Backbone 0.5.2 開始,bind() 方法就開始接受使用第三個參數來定義回調函數的對象。(在上述示例中,當前視圖是回調函數 render() 中的對象)。在 Backbone 0.5.2 之前的版本中,必須使用 underscore.js 中的 bindAll 函數,如 清單 22 所示。

清單 22. _.bindAll() usage

// In the following view, el value is 'div.team-element'
App.Views.Team = Backbone.View.extend({
  initialize : function() {
    _.bindAll(this, "render");
    this.model.bind("change", this.render);
  } 
})

Backbone 視圖中,通過視圖中的 DOM 對象監聽事件是比較容易的。對于實現這一點,events 屬性很是方便的,如 清單 23 所示。

清單 23. 事件屬性

App.Views.Team = Backbone.View.extend({
  className : '.team-element',
  tagName : 'div',
  events : {
    "click a.more" : "moreInfo"
  },
  moreInfo : function(e){
     // Logic here
  }
})

events 屬性的每個項均由兩部分構成:

  1. 左邊部分指定事件類型和觸發事件的選擇器。
  2. 右邊部分定義了事件處理函數。

在 清單 23 中,當用戶通過 DIV 中的類 more 以及類 team-element 點擊鏈接時,會調用函數 moreInfo

結束語

MVC 模式可以為大型 JavaScript 應用程序提供所需的組織化代碼。Backbone 是一個 JavaScript MVC 框架,它屬于輕量級框架,且易于學習掌握。模型、視圖、集合和路由器從不同的層面劃分了應用程序,并負責處理幾種特定事件。處理 Ajax 應用程序或者 SPI 應用程序時,Backbone 可能是最好的解決方案。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黑河市| 大悟县| 四川省| 信阳市| 儋州市| 南部县| 云霄县| 中西区| 南溪县| 开鲁县| 洪湖市| 宝鸡市| 孟津县| 遵义县| 额济纳旗| 宜都市| 天气| 孙吴县| 六安市| 昌都县| 广西| 静安区| 舞钢市| 北流市| 类乌齐县| 广南县| 松江区| 香河县| 滦南县| 磐安县| 桃园县| 梁平县| 谷城县| 手机| 黄平县| 阳谷县| 鞍山市| 花莲县| 东平县| 改则县| 五常市|