91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

如何理解Backbone.js 的技巧和模式

發布時間:2021-11-17 15:25:07 來源:億速云 閱讀:138 作者:柒染 欄目:web開發

這篇文章將為大家詳細講解有關如何理解Backbone.js 的技巧和模式,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

Backbone.js是一個開源JavaScript“MV*”框架, 在三年前它的第一次發布的時候就獲得了顯著的推動。盡管Backbone.js為Javascript應用程序提供了自己的結構,但它留下了大量根據開發 者的需要而使用的設計模式和決策,并且當開發者們第一次使用Backbone.js開發的時候都會遇到許多共同的問題。

因此,在這篇文章中,我們除了會探索各種各樣你能夠應用到你的Backbone.js應用中的設計模式外,我們也會關注一些困惑開發者的常見問題。

執行對象的深復制

JavaScript中所有原始類型變量的傳遞都是值傳遞。所以,當變量被引用的時候會傳遞該變量的值。

var helloWorld = “Hello World”; var helloWorldCopy = helloWorld;

例如,以上代碼會將helloWorldCopy 的值設為helloWorld的值。所以對于helloWorldCopy 的所有修改都不會改變helloWorld, 因為它是一個拷貝。另一方面,JavaScript所有非原始類型變量的傳遞都是引用傳遞,意思是當變量被引用的時候,JavaScript會傳遞一個其內存地址的參照。

var helloWorld = {     ‘hello’: ‘world’ } var helloWorldCopy = helloWorld;

舉個例子,上面的代碼會將helloWorldCopy 設為helloWorld  對象的別名,此時,你可能會猜到,對helloWorldCopy 的所有修改都會直接在helloWorld  對象上進行。如果你想得到一個helloWorld 對象的拷貝,你必須對這個對象進行一次復制。

你可能想知道,“為什么他(作者)要在這篇文章中解釋這些按引用傳遞的東西?”很好,這是因為在Backbone.js的對象傳遞中,并不對進行對象復制,意味著如果你在一個模型中調用 get( ) 方法來取得一個對象,那么對它的任何修改都會直接在模型中的那個對象進行操作!讓我們通過一個例子來看看什么時候它會成為你的麻煩。假設現在你有一個如下的Person 模型:

var Person = Backbone.Model.extend({    defaults: {         'name': 'John Doe',         'address': {             'street': '1st Street'             'city': 'Austin',             'state': 'TX'             'zipCode': 78701         }    } });

并且假設你創建了一個新的person 對象:

var person = new Person({     'name': 'Phillip W' });

現在讓我們對新對象person 的屬性做一點修改。

person.set('name', 'Phillip W.');

上述代碼會對person 對象中的name 屬性進行修改。接下來讓我們嘗試修改person 對象的address 屬性。在這之前,我們先對address屬性添加校驗。

var Person = Backbone.Model.extend({     validate: function(attributes) {          if(isNaN(attributes.address.zipCode)) return "Address ZIP code must be a number!";     },      defaults: {         'name': 'John Doe',         'address': {             'street': '1st Street'             'city': 'Austin',             'state': 'TX'             'zipCode': 78701         }     }  });

現在,我們會嘗試使用一個不正確的ZIP 碼來修改對象的address 屬性。

var address = person.get('address'); address.zipCode = 'Hello World';// 應該產生一個一個錯誤因為ZIP碼是無效的 person.set('address', address); console.log(person.get('address')); /* 打印包含如下屬性的對象. {     'street': '1st Street'     'city': 'Austin',     'state': 'TX'     'zipCode': 'Hello World' } */

為什么會這樣?我們的校驗方法不是已經返回一個錯誤了嗎?!為什么attributes 屬性還是被改變了?原因正如前面所說,Backbone.js不會復制模型的attributes對象; 它僅僅返回你所請求的東西。所以,你可能會猜到,如果你請求的是一個對象(如上面的address),你會得到那個對象的引用,并且你對這個對象的所有修 改都會直接地操作在模型中的實際對象中(因此這樣的修改方式并不會導致校驗失敗,因為對象的引用并沒有改變)。這個問題很可能會導致你花費幾小時來進行調 試和診斷。

這個問題會逮住一些使用Backbone,js的新手甚至經驗豐富卻不夠警惕的JavaScript開發者。這個問題已經在GitHub issues 的Backbone.js部分引起了大量的討論。像 Jeremy Ashkenas 所指出的,執行深復制是一個非常棘手的問題,對那些有較大深度的對象來說,它將會是個非常昂貴的操作。

幸運地,jQuery提供了一些深復制的實現,$.extend。順帶說一句,Underscore.js,Backbone.js的一個依賴插件,也提供了類似的方法 _.extend ,但我會避免使用它,因為它并不執行深復制。

var address = $.extend(true, {}, person.address);

我們現在得到了 address 對象的一個精確的拷貝,因此我們可以隨心所欲地修改它的內容而不用擔心修改到person中的address  對象。你應該意識到此模式適用于上述那個例子僅因為address 對象的所有成員都是原始值(numbers, strings,  等等),所以當深復制的對象中還包含有子對象時必須謹慎地使用。你應該知道執行一個對象的深復制會產生一個小的性能影響,但我從沒見過它導致了什么顯而易 見的問題。盡管這樣,如果你對一個復雜對象的執行深復制或者一次性執行上千個對象的深復制,你可能會想做一些性能分析。這正是下一個模式出現的原因。

為對象創建Facades

在真實的世界里,需求經常會更改,所以那些通過模型和集合的查詢而從終端返回的JSON數據也會有所改變。如果你的視圖與底層數據模型緊緊地耦合,這將會讓你感到非常麻煩。因此,我為所有的對象創建了獲取器和設置器

很多人贊成這種模式。就是如果任何底層數據結構被改變,視圖層不應該更新太多;當你只有一個數據入口的時候,你就不太可能忘記執行深復制,并且你的代碼會變得更加可維護和調試。但帶來的負面影響是這種模式會讓你的模型和集合有點膨脹。

讓我們通過一個例子來搞清楚這個模式。假設我們有一個Hotel 模型,其中包含了rooms和當前可用的rooms,我們希望能夠通過床位尺寸值來取得相應的rooms。

var Hotel = Backbone.Model.extend({     defaults: {         "availableRooms": ["a"],         "rooms": {             "a": {                 "size": 1200,                 "bed": "queen"             },             "b": {                 "size": 900,                 "bed": "twin"             },             "c": {                 "size": 1100,                 "bed": "twin"             }         },          getRooms: function() {             $.extend(true, {}, this.get("rooms"));         },          getRoomsByBed: function(bed) {             return _.where(this.getRooms(), { "bed": bed });         }     } });

讓我們假設明天你將會發布你的代碼,并且終端的開發者忘記告訴你rooms的數據結構從Object變成了一個array。你的代碼現在如下所示:

var Hotel = Backbone.Model.extend({     defaults: {         "availableRooms": ["a"],         "rooms": [             {                 "name": "a",                 "size": 1200,                 "bed": "queen"             },             {                 "name": "b",                 "size": 900,                 "bed": "twin"             },             {                 "name": "c",                 "size": 1100,                 "bed": "twin"             }         ],          getRooms: function() {             var rooms = $.extend(true, {}, this.get("rooms")),              newRooms = {};             // transform rooms from an array back into an object             _.each(rooms, function(room) {                 newRooms[room.name] = {                     "size": room.size,                     "bed": room.bed                 }             });         },          getRoomsByBed: function(bed) {             return _.where(this.getRooms(), { "bed": bed });         }     } });

為了將Hotel  轉換為應用所期望的數據結構,我們僅僅更新了一個方法,這讓我們整個App的仍然正常工作。如果我們沒有創建一個rooms數據的獲取器,我們可能不得不 更新每一個rooms的數據入口。理想情況下,你為了使用一個新的數據結構而會想要更新所有的接口方法。但如果由于時間緊迫而不得不盡快發布代碼的話,這 個模式能拯救你。

順帶提一下,這個模式既可以被認為是一個facade 設計模式,因為它隱藏了對象復制的細節,也可以被稱為 bridge 設計模式,因為它可以被用于轉換所期望的數據結構。因而一個好的習慣是在所有的對象上使用獲取器和設置器。

存儲數據但不同步到服務器

盡管Backbone.js規定模型和集合會映射到REST-ful終端,但你有時候會發現你只是想將數據存儲在模型或者集合而不同步到服務器。一些其他關于Backbone.js的文章,像“Backbone.js Tips: Lessons From the Trenches”就講解過這個模式。讓我們快速地通過一個例子來看看什么時候這個模式會派上用場。假設你有個ul列表。

<ul>     <li><a href="#" data-id="1">One</a></li>     <li><a href="#" data-id="2">Two</a></li>     . . .     <li><a href="#" data-id="n">n</a></li> </ul>

當n值為200并且用戶點擊了其中一個列表項,那個列表項會被選中并添加了一個類以直觀地顯示。實現它的一個方法如下所示:

var Model = Backbone.Model.extend({     defaults: {         items: [             {                 "name": "One",                 "id": 1                        },             {                 "name": "Two",                 "id": 2                        },             {                 "name": "Three",                 "id": 3                        }         ]     } });  var View = Backbone.View.extend({     template: _.template($('#list-template').html()),      events: {         "#items li a": "setSelectedItem"     },      render: function() {         $(this.el).html(this.template(this.model.toJSON()));     },      setSelectedItem: function(event) {         var selectedItem = $(event.currentTarget);        // Set all of the items to not have the selected class         $('#items li a').removeClass('selected');         selectedItem.addClass('selected');         return false;     } });  <script id="list-template" type="template">     <ul id="items">             <% for(i = items.length - 1; i >= 0; i--) { %>         <li>                     <a href="#" data-id="<%= item[i].id %>"><%= item[i].name %></a></li>     <% } %></ul> </script>

現在我們想要知道哪一個item被選中。一個方法是遍歷整個列表。但如果這個列表過長,這會是一個昂貴的操作。因此,當用戶點擊其中的列表項時,我們應該將它存儲起來

var Model = Backbone.Model.extend({     defaults: {         selectedId: undefined,         items: [             {                 "name": "One",                 "id": 1             },             {                 "name": "Two",                 "id": 2             },             {                 "name": "Three",                 "id": 3             }         ]     } });  var View = Backbone.View.extend({     initialize: function(options) {        // Re-render when the model changes         this.model.on('change:items', this.render, this);     },      template: _.template($('#list-template').html()),      events: {         "#items li a": "setSelectedItem"     },      render: function() {         $(this.el).html(this.template(this.model.toJSON()));     },      setSelectedItem: function(event) {         var selectedItem = $(event.currentTarget);        // Set all of the items to not have the selected class         $('#items li a').removeClass('selected');         selectedItem.addClass('selected');        // Store a reference to what item was selected         this.model.set('selectedId', selectedItem.data('id'));         return false;     } });

現在我們能夠輕易地搜索我們的模型來確定哪一個item被選中,并且我們避免了遍歷文檔對象模型 (DOM)。這個模式對于存儲一些你想要跟蹤的外部數據非常有用;還要記住的是你能夠創建不需要與終端相關聯的模型和集合。

這個模式的消極影響是你的模型或集合并不是真正地采用RESTful 架構因為它們沒有完美地映射到網絡資源。另外,這個模式會讓你的模型帶來一點兒膨脹;并且如果你的終端嚴格地只接收它所期望的JSON數據,它會給你帶來一點兒麻煩。

渲染視圖的一部分而不是渲染整個視圖

當你第一次開發Backbone.js應用,你的視圖一般會是這樣的結構:

var View = Backbone.View.extend({     initialize: function(options) {         this.model.on('change', this.render, this);     },      template: _.template($(&lsquo;#template&rsquo;).html()),      render: function() {         this.$el.html(template(this.model.toJSON());         $(&lsquo;#a&rsquo;, this.$el).html(this.model.get(&lsquo;a&rsquo;));         $(&lsquo;#b&rsquo;, this.$el).html(this.model.get(&lsquo;b&rsquo;));     } });

在這里,你的模型的任何改變都會觸發一次視圖的完整的重新渲染。當我第一次使用Backbone.js來做開發的時候,我也使用過這種模式。但隨著我代碼的膨脹,我很快意識到這個方法是不可維護和不理想的,因為模型的任何屬性的改變都會讓視圖完全重新渲染。

當我遇到這個問題的時候,我馬上在Google搜索其他人是怎么做的并且找到了Ian Storm Taylor的博客寫的一篇文章, “Break Apart Your Backbone.js Render Methods,”,其中他提到了監聽模型個別的屬性改變并且響應的方法僅僅重新渲染視圖的一部分。Taylor也提到重渲染方法應該返回自身的this對象,這樣那些單獨的重渲染方法就可以輕易地串聯起來。下面的這個例子已經作出了修改而變得更易于維護和管理了,因為當模型屬性改變的時候我們僅僅更新相應部分的視圖。

var View = Backbone.View.extend({     initialize: function(options) {         this.model.on('change:a', this.renderA, this);         this.model.on('change:b', this.renderB, this);     },      renderA: function() {         $(&lsquo;#a&rsquo;, this.$el).html(this.model.get(&lsquo;a&rsquo;));         return this;     },      renderB: function() {         $(&lsquo;#b&rsquo;, this.$el).html(this.model.get(&lsquo;b&rsquo;));         return this;     },      render: function() {         this             .renderA()             .renderB();     } });

還要提到的是,許多插件,像 Backbone.StickIt 和 Backbone.ModelBinder,提供了視圖元素和模型屬性之間的鍵值綁定,這能夠節省你很多的相似代碼。因此,如果你有很多復雜的表單字段,可以試著使用它們。

保持模型和視圖分離

像Jeremy Ashkenas 在Backbone.js的 GitHub issues指出的一個問題,除了模型不能夠由它們的視圖來創建以外,Backbone.js并不在數據層和視圖層之間實施任何真正的關注點分離。你覺得應該在數據層和視圖層之間實施關注點分離嗎?我和其他的一些Backbone.js開發者,像Oz Katz和 Dayal,都認為這個答案毫無疑問應該是要的:模型和集合,代表著數據層,應該禁止任何綁定到它們的視圖的入口,從而保持一個完全的關注點分離。如果你不遵循這個關注點分離,你的代碼很快就會變得像意大利面條那樣糾纏不清,而沒有人會喜歡這種代碼

保持你的數據層和視圖層完全地分離可以使你擁有更加地模塊化,可重用和可維護的代碼。你能夠輕易地在你的應用中重用和拓展模型和集合而不需要擔心和他們綁定的視圖。遵循這個模式能讓新加入項目的開發者快速的投入到代碼中。因為它們精確的知道哪里會發生視圖的渲染以及哪里存放著應用的業務邏輯。

這個模式也強制使用了單一責任原則,該原則規定了每一個類應該只有一個單獨的責任,并且它的職責應該封裝在這個類中,因為你的模型和集合應該只負責處理數據,視圖應該只負責處理渲染。

路由器中的參數映射

使用例子是展示這個模式如何產生的最好方法。例如:有一些搜索頁面,它們允許用戶添加兩個不同的過濾類型,foo 和bar,每一個都附有大量的選項。因此,你的URL結構看起來將會像這樣:

'search/:foo' 'search/:bar' 'search/:foo/:bar'

現在,所有的路由使用一個確切的視圖和模型,所以,理想狀況下,你會樂意它們都用同一個方法,search()。但是,如果你檢查 Backbone.js,會發現沒有任何形式的參數映射;這些參數只是簡單地從左到右扔到方法里面去。所以,為了讓它們都能使用相同的方法,你最終要創建 不同的方法來正確地映射參數到search()方法。

routes: {     'search/:foo': 'searchFoo',     'search/:bar': 'searchBar',     'search/:foo/:bar': 'search' },  search: function(foo, bar) {     }, // I know this function will actually still map correctly, but for explanatory purposes, it's left in. searchFoo: function(foo) {     this.search(foo, undefined); },  searchBar: function(bar) {     this.search(undefined, bar); },

和你想的一樣,這種模式會快速地膨脹你的路由。當我第一次使用接觸這種模式的時候,我嘗試使用正則表達式在實際方法定義中做一些解析而“神奇地”映 射這些參數,但這只能在參數容易區分的情況下起作用。所以我放棄了這個方法(我有時候依然會在Backbone插件中使用它)。我在issue on GitHub上提出過這個問題,Ashkenas 給我的建議是在search方法中映射所有的參數。

下面這段代碼已經變得更加具備可維護性:

routes: {     'base/:foo': 'search',     'base/:bar': 'search',     'base/:foo/:bar': 'search' },  search: function() {     var foo, bar, i;      for(i = arguments.length - 1; i >= 0; i--) {          if(arguments[i] === 'something to determine foo') {             foo = arguments[i];             continue;         }         else if(arguments[i] === 'something to determine bar') {             bar = arguments[i];             continue;         }     } },

這個模式可以徹底地減少路由器的膨脹。然而,要意識到它對于不可識別的參數時無效的。舉個例子,如果你有兩個傳遞ID的參數并且都它們以 XXXX-XXXX 這種模式表現,你將無法確定哪一個ID對應的是哪一個參數。

model.fetch() 不會清除你的模型

這個問題通常會絆倒使用Backbone.js的新手: model.fetch() 并不會清理你的模型,而是會將取回來的數據合并到你的模型當中。因此,如果你當前的模型有x,,y 和 z 屬性并且你通過fetch得到了一個新的 y 和z 值,接下來 x 會保持模型原來的值,僅僅 y 和z 的值會得到更新,下面這個例子直觀地說明了這個概念。

var Model = Backbone.Model.extend({     defaults: {         x: 1,         y: 1,         z: 1     } }); var model = new Model(); /* model.attributes yields {     x: 1,     y: 1,     z: 1 } */ model.fetch(); /* let&rsquo;s assume that the endpoint returns this {     y: 2,     z: 2, } */ /* model.attributes now yields {     x: 1,     y: 2,     z: 2 } */

PUT請求需要一個ID屬性

這個問題也只通常出現在Backbone.js的新手中。當你調用.save() 方法時,你會發送一個HTTP PUT  請求,要求你的模型已經設置了一個ID屬性。HTTP PUT  是被設計為一個更新動作的,所以發送PUT請求的時候要求你的模型已有一個ID屬性是合情理的。在理想的世界里,你的所有模型都會有一個名為id的屬性, 但現實情況是,你從終端接收的JSON數據的ID屬性并不總是會剛好命名為id。

因此,如果你需要更新你的模型,請確定在保存前你的模型具有一個ID。當終端返回的ID屬性變量名不為 id 的時候,0.5及以上的版本的Backbone.js允許你使用 idAttribute 來改變ID屬性的名字。

如果使用的Backbone.js的版本仍低于0.5,我建議你修改集合或模型中的 parse 方法來映射期望的ID屬性到真正的ID屬性。這里有一個讓你快速掌握這個技巧的例子,讓我們假設你有一個cars集合,它的ID屬性名為carID .

parse: function(response) {      _.each(response.cars, function(car, i) {        // map the returned ID of carID to the correct attribute ID         response.cars[i].id = response.cars[i].carID;     });      return response; },

頁面加載中的模型數據

一些時候你會發現你需要在頁面加載的時候就使用數據來初始化你的集合和模型。一些關于Backbone.js模式的文章,像Rico Sta Cruz的“Backbone Patterns”和Katz的“Avoiding Common Backbone.js Pitfalls,”談論到了這個模式。使用你選擇的服務端語言,通過嵌入代碼到頁面并將數據放在單個模型的屬性或JSON當中,你能夠輕易地實現這個模式。舉個例子,在Rails中,我會這樣使用:

// a single attribute var model = new Model({     hello: <%= @world %> });// or to have json var model = new Model(<%= @hello_world.to_json %>);

使用這個模式能夠通過“馬上渲染你的頁面”來提高你的搜索引擎排名,并且它能通過限制應用的HTTP請求來徹底地縮短你的應用啟動和運行所花費的時間。

處理驗證失敗的模型屬性

你經常會想知道哪一個模型屬性的驗證失敗了。舉個例子,如果你有一個極度復雜的表單域,你可能想知道哪一個模型屬性驗證失敗,這樣你能夠高亮顯示相 應的表單域。不幸的是,提醒你的視圖哪一個模型屬性驗證失敗并沒有直接在Backbone.js中實現,但你可以使用不同的模式來處理這個問題。

返回一個錯誤對象

通知你的視圖哪一個模型屬性驗證失敗的一個模式是回傳一個帶有某種標志的對象,該對象中詳述哪一個模型屬性驗證失敗,就像下面這樣:

// Inside your model validate: function(attrs) {     var errors = [];      if(attrs.a < 0) {         errors.push({             'message': 'Form field a is messed up!',             'class': 'a'         });     }     if(attrs.b < 0) {         errors.push({             'message': 'Form field b is messed up!',             'class': 'b'         });     }      if(errors.length) {         return errors;     } }// Inside your view this.model.on('invalid&rsquo;, function(model, errors) {     _.each(errors, function(error, i) {         $(&lsquo;.&rsquo; + error.class).addClass('error');         alert(error.message);     }); });

這個模式的優點是你在一個位置處理了所有的無效信息。缺點是如果你處理不同的無效屬性,你的屬性校驗部分會變為一個比較大的 switch 或 if 語句。

廣播傳統錯誤事件

由我朋友Derick Bailey建議的一個替換的模式,是對個別的模型屬性觸發自定義錯誤事件。這能讓你的視圖為個別的屬性綁定指定的錯誤事件。

// Inside your model validate: function(attrs) {      if(attrs.a < 0) {             this.trigger(&lsquo;invalid:a&rsquo;, 'Form field a is messed up!', this);     }     if(attrs.b < 0) {             this.trigger(&lsquo;invalid:b&rsquo;, 'Form field b is messed up!', this);     } }// Inside your view this.model.on('invalid:a&rsquo;, function(error) {         $(&lsquo;a&rsquo;).addClass('error');         alert(error); }); this.model.on('invalid:b&rsquo;, function(error) {         $(&lsquo;b&rsquo;).addClass('error');         alert(error); });

這個模式的優點是你的視圖綁定了明確類型的錯誤事件,并且如果你對每一類型的屬性錯誤有明確的執行指令,它能整頓你視圖代碼并使它更加可維護。這個模式的一個缺點是如果存在太多不同的想要處理的屬性錯誤,你的視圖代碼會變得更加臃腫。

兩個模式都有他們的優缺點,所以在你應該考慮哪一種模式更加適合你的用例。如果你想對所有的驗證失敗處理都采用一個方法,那第一個方法會是個好選擇;如果你的每一個模型屬性都有明確的UI改變,那選第二個方法會更好。

HTTP狀態碼200觸發錯誤

如果你的模型或集合訪問的終端返回了無效的JSON數據,它們會觸發一個“error”事件,即使你的終端返回的HTTP狀態碼是200。這個情況通常出現在根據模擬JSON數據來做本地開發的時候。所以一個好方法是把你正在開發中的所有的模擬JSON文件都扔到JSON 驗證器中檢驗。或者為你的IDE安裝一個插件可以捕捉任何格式錯誤的JSON。

創建一個通用的錯誤展示

創建一個通用的錯誤展示意味著你有一個統一的模式來處理和顯示錯誤信息,這能夠節省你的時間,并能提升用戶的整體體驗。在我開發的任何的Backbone.js 應用中我都創建了一個通用的視圖來處理警告。

var AlertView = Backbone.View.extend({     set: function(typeOfError, message) {         var alert = $(&lsquo;.in-page-alert&rsquo;).length ? $(&lsquo;.in-page-alert&rsquo;): $(&lsquo;.body-alert&rsquo;);         alert             .removeClass(&lsquo;error success warning&rsquo;)             .html(message)             .fadeIn()             .delay(5000)             .fadeOut();     } });

上面這個視圖首先查看在視圖之內是否已經聲明了 in-page-alert div。如果沒有聲明,它會回到被聲明在布局的某個地方的通用  body-alert div中。這讓你能夠傳遞一個一致的錯誤信息給你用戶,并在你忘記指定一個特定的 in-page-alert  div時提供有效的備用div。上面的模式簡化了你在視圖中對錯誤信息的處理工作,如下面所示:

this.model.on('error', function(model, error) {     alert.set('TYPE-OF-ERROR', error); });

更新單頁應用的文檔標題

這比關注任何東西都更加有用。如果你正在開發一個單頁應用,請記得更新每一頁的文檔標題!我寫過一個簡單的Backbone.js插件,Backbone.js Router Title Helper,它通過拓展Backbone.js路由器來簡單又優雅地實現這個功能。它允許你指定一個標題的對象常量,它的鍵映射到路由的方法名,值則是頁標題。

Backbone.Router = Backbone.Router.extend({      initialize: function(options){         var that = this;          this.on('route', function(router, route, params) {              if(that.titles) {                 if(that.titles[router]) document.title = that.titles[router];                 else if(that.titles.default) document.title = that.titles.default;                 else throw 'Backbone.js Router Title Helper: No title found for route:' + router + ' and no default route specified.';             }         });     } });

在單頁應用中緩存對象

當我們討論單頁應用的時候,你有必要遵循的另一個模式是緩存那些將會被重復使用的對象。這個技巧是相當簡單和直接的:

// Inside a router initialize: function() {      this.cached = {         view: undefined,         model: undefined     } },  index: function(parameter) {     this.cached.model = this.cached.model || new Model({         parameter: parameter     });     this.cached.view = this.cached.view || new View({         model: this.cached.model     }); }

這個模式將會讓你的應用像小石子那般飛快起來,因為你不需要重新初始化你的Backbone.js對象。然而,它可能會導致你的應用的內存占用變得相當大;因此,我一般僅僅緩存那些貫穿整個應用的對象。如果你以前開發過Backbone.js應用,你可能會問自己“如果我想重新獲取數據會怎樣?”那么你可以在每次路由被觸發的時候重新獲取數據。

// Inside a router initialize: function() {      this.cached = {         view: undefined,         model: undefined     } },  index: function(parameter) {     this.cached.model = this.cached.model || new Model({         parameter: parameter     });     this.cached.view = this.cached.view || new View({         model: this.cached.model     });     this.cached.model.fetch(); }

當你的應用必須從終端中取回最新數據的時候(例如,一個收信箱),這個模式會很好用。然而,如果你正在取回的數據依賴應用的狀態(假設狀態是靠你的URL 和參數維持的),那即使自用戶上一次瀏覽頁面以來應用的狀態沒有改變,你仍會更新數據。一個比較好的解決辦法是僅當應用的狀態(parameter)被改 變的時候才更新數據。

// Inside a router initialize: function() {      this.cached = {         view: undefined,         model: undefined     } },  index: function(parameter) {     this.cached.model = this.cached.model || new Model({         parameter:parameter     });     this.cached.model.set('parameter', parameter);     this.cached.view = this.cached.view || new View({         model: this.cached.model     }); } // Inside of the model initialize: function() {     this.on("change:parameter", this.fetchData, this); }

JSDoc功能和Backbone.js的類

我喜歡編制文檔并且是JSDoc的忠實粉絲,我用JSDoc 為所有遵循下面所示格式的Backbone 類和方法生成了文檔:

var Thing = Backbone.View.extend(/** @lends Thing.prototype */{     /** @class Thing      * @author Phillip Whisenhunt      * @augments Backbone.View      * @contructs Thing object */     initialize() {},      /** Gets data by ID from the thing. If the thing doesn't have data based on the ID, an empty string is returned.      * @param {String} id The id of get data for.      * @return {String} The data. */     getDataById: function(id) {} });

如果你為上面這種格式的Backbone類編制文檔,你可以編制一份漂亮的文檔,它包含你所有的類和帶有參數,返回值和描述的方法。請確保initialize 始終是第一個聲明的方法,因為這有助于生成JSDoc。如果你想要看一個使用JSDoc的項目的例子,請查閱HomeAway Calendar Widget。有個 Grunt.js 插件,grunt-jsdoc-plugin 插件,使用它們會把生成文檔作為構建過程的一部分。

實踐測試驅動開發

在我看來,如果你正在使用Backbone.js,你應該讓你模型和集合遵循測試驅動開發(TDD)。我通過第一次為我的模型和集合編寫失敗的 Jasmine.js  單元測試而開始遵循TDD。一旦我寫的單元測試編寫和失敗,我就把模型和集合排出。通過這一點,我所有的Jasmine  測試將會被傳遞,并且我有信心我的模型方法全部都會像預期般工作。因為我一直遵循TDD,我的視圖層已經可以相當容易地編寫并會極度地輕薄。當你剛開始實 踐TDD的時候,你肯定會慢下來;不過一旦你深入其中,你的生產力和代碼質量都會大大提升。

關于如何理解Backbone.js 的技巧和模式就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

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

AI

大厂| 北碚区| 静宁县| 清远市| 炉霍县| 邵阳市| 四会市| 馆陶县| 大邑县| 大同县| 广州市| 彰化县| 抚州市| 类乌齐县| 苏州市| 阳信县| 河东区| 抚顺县| 永丰县| 大理市| 囊谦县| 中超| 潜山县| 会同县| 阳春市| 鄯善县| 永仁县| 老河口市| 宣恩县| 桦川县| 东宁县| 密云县| 东源县| 甘南县| 天水市| 新疆| 剑河县| 天门市| 彰化市| 海门市| 蒙自县|