《BackboneJS架構的技巧及模式》(4)完結篇

來源:互聯網
上載者:User


本文緊接第二部分:《BackboneJS架構的技巧及模式(3)》

作者:chszs,轉載需註明。部落客頁:http://blog.csdn.net/chszs

八、PUT需要一個ID屬性

這一條也經常會對那些Backbone.js新手造成困擾。要想在調用.save()的時候讓模型發送一個HTTP PUT請求,你的模型需要有一個ID屬性集。記得HTTP PUT謂詞是設計用做更新的吧,所以發送一PUT請求,你的模型需要有一個ID。在理想情況,你的所有模型都有一名為ID的完美ID屬性,但是你從端點接收到的JSON資料或許並不總是有完美命名的ID。

因此,如果你需要更新一個模型,在儲存前確保模型上帶有ID。Backbone.js從0.5版開始允許使用idAttribute來修改模型ID屬性的名稱,如果端點返回的不是名為id的ID屬性名稱時。

如果使用的Backbone.js版本低於0.5,建議你修改模型或集合的parse函數,以便將期望的ID屬性對應到屬性ID。這裡有一個快速上手的例子,說明了應怎樣修改parse函數來做到這一點。我們假設你有一個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模式”和Katz的“避免常見的Backbone.js陷阱”,討論了這種模式。這種模式實現很容易,只需在頁面中內聯一段指令碼,通過你選擇的服務端語言,將單個模型屬性或者JSON形式的資料呈現出來。例如,在Rails語言中,我採用下面的一種方法:

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

應用此模式可以通過“立即”渲染頁面,以改善你網站的搜尋引擎排名,而且它也可通過限制應用初始化HTTP請求的方式,大幅縮短應用啟動與運行所需的時間。

十、處理失敗的模型屬性驗證

很多時候,你會想知道是哪個模型屬性驗證失敗了。例如,如果你有一個極其複雜的表單欄位,你或許想知道哪一個模型屬性驗證失敗了,以便於你可以將該屬性對應的輸入欄位進行高亮顯示。不幸的是,警告視圖到底是哪個模型屬性驗證失敗並沒有直接整合於Backbone.js,但是你可以用其他不同的模式去處理這個問題。

1、返回一個錯誤對象

一個通知視圖是哪個模型屬性驗證失敗的模式是,返回一個對象,其中包含某種標誌,它詳細的記錄了驗證失敗的屬性,就像下面這樣:

// Inside your modelvalidate: 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 viewthis.model.on('invalid’, function(model, errors) {    _.each(errors, function(error, i) {        $(‘.’ + error.class).addClass('error');        alert(error.message);    });});

此模式的優點在於,你可以在一個地方處理所有無效的訊息。缺點在於,如果你用不同的invalid屬性處理無效屬性,那麼你的invalid方法裡面可能會有非常龐大的switch語句或if語句。

2、廣播自訂的Error事件

我的朋友Derick Bailey推薦了一個可替代的模式,就是為每個模型屬性觸發自訂的errors事件。它允許你的視圖能夠針對單獨的屬性綁定特定的error事件:

// Inside your modelvalidate: function(attrs) {    if(attrs.a < 0) {            this.trigger(‘invalid:a’, 'Form field a is messed up!', this);    }    if(attrs.b < 0) {            this.trigger(‘invalid:b’, 'Form field b is messed up!', this);    }}// Inside your viewthis.model.on('invalid:a’, function(error) {        $(‘a’).addClass('error');        alert(error);});this.model.on('invalid:b’, function(error) {        $(‘b’).addClass('error');        alert(error);});

此模式的優點在於,你的視圖綁定的error類型是清晰的,並且對於每一種error屬性,可以有特定的指令,它可以使得視圖方面的代碼很清晰,使之更易於維護。此模式的缺點在於,視圖的代碼可能會變得極為膨脹。

這兩種模式都各有利弊,你應該考慮清楚哪個模式對你的應用案例是最優的。如果你按照同樣的方式處理所有失敗的驗證,那麼第一個方法可能是最好的;如果你對每個模型屬性有特定的UI變化,那麼後一種方法會更好。

十一、HTTP狀態代碼200觸發錯誤

如果終端的模型或集合收到了無效的JSON,儘管終端返回了HTTP狀態代碼200,模型或集合還是會觸發error事件。這種問題經常發生於開發階段在本地類比JSON資料造成的。那麼,有個好方法是拋出經過 JSON 驗證器驗證了的類比JSON資料檔案。或者使用IDE的外掛程式來及時捕獲格式錯誤的JSON資料。

十二、建立通用的錯誤顯示

這能夠節省開發時間以及建立統一的模式來處理和可視化錯誤訊息,而且它可以改善整個的使用者體驗。我之前開發的每一個Backbone.js應用中,我都會建立一個通用的警告視圖:

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

上面代碼首先會檢查視圖代碼中是否存在指定in-page-alert視圖的DIV元素。如果沒有,則接著查看通用的body-alert的DIV元素,它可以在布局中進行聲明。這可以交付一致性的錯誤資訊給使用者,而且一旦你忘記指定in-page-alert視圖的DIV元素,它會有一個有用的反饋。下面的模式簡化了怎樣在試圖中處理錯誤資訊:

var alert = new AlertView();this.model.on('error', function(model, error) {    alert.set('TYPE-OF-ERROR', error);});
十三、單頁面應用中更新頁面標題

如果你正在開發一個單頁面應用,切記要更新每個頁面的標題。我寫過一個簡單的外掛程式(Backbone.js Router Title Helper),它以簡單、優雅的格式擴充了 backbone.js router 的功能。它通過一個 Map 對象來控制路由,鍵來代表路由函數的名字,值則映射到頁面的標題。

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.';            }        });    }});

1、在單頁應用中緩衝對象

當談論單頁應用時,緩衝對象的模式會經常用到!下面的例子簡明扼要:

// Inside a routerinitialize: 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 routerinitialize: 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和參數來決定的),那麼即使應用程式的狀態為發生改變,也應該重新取回資料。更好的解決方案是只在應用程式的參數發生變化時重新取回資料:

// Inside a routerinitialize: 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 modelinitialize: 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類添加文檔注釋,那麼你可以產生優美的文檔,文檔包含了所有的類和函數及參數。確保初始化函數應作為第一個聲明的函數,它可以協助我們產生JSDoc文檔。如果你想看使用JSDoc的項目例子,這裡有:
https://github.com/homeaway/calendar-widget

十五、測試驅動的開發實踐

我認為如果你使用Backbone.js開發項目,那麼你應遵循測試驅動開發TDD。我第一次用Jasmine.js建立模型和集合時遵循TDD進行單元測試,但失敗了。一旦寫下單元測試並且失敗,我會對整個模型和集合進行重寫。

通過這一點,我的所有Jasmine測試都通過了,而且我有信心我的模型及集合會和我期望的一樣工作。自從我遵循TDD,我的視圖層非常容易編寫而且非常簡單。當你開始用TDD時,你的開發速度當然會很慢;但是一但你的腦海裡一直想著TDD,你的編程效率和品質會顯著提高。




相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.