2013-05-13 56 views
3

我試圖找出在Backbone.js模型中完成自定義更新 函數的「正確」方法。什麼我想要做的一個例子是:爲主幹模型添加功能?

var Cat = Backbone.Model.extend({ 

    defaults: { 
    name  : 'Mr. Bigglesworth', 
    location : 'Living Room', 
    action : 'sleeping' 
    }, 

    sleep: function() { 
    // POST /cats/{{ cat_id }}/action 
    // { action: "sleep" } 
    }, 

    meow: function() { 
    // POST /cats/{{ cat_id }}/action 
    // { action: "meow" } 
    } 

}) 

從我所知道的,Backbone.Collection.save()方法如下只執行 :

POST /cats/{{ cat_id }} 
{ name: 'Mr. Bigglesworth', location: 'Living Room', action: '{{ value }} '} 

但API我與韓元工作我不會讓這樣改變,只能通過:

POST /cats/{{ cat_id }}/action 
{ action: "{{ value }}" } 

希望這有道理嗎?

任何幫助,將不勝感激。

回答

4

當您調用保存時,您可以將URL作爲參數傳遞。也許你可以這樣做:

var Cat = Backbone.Model.extend({ 
    urlRoot: '/cats/', 

    defaults: { 
    name  : 'Mr. Bigglesworth', 
    location : 'Living Room', 
    action : 'sleeping' 
    }, 

    sleep: function() { 
    var custom_url = this.urlRoot + this.id + "/action"; 
    this.save({}, { url: custom_url}); 
    // POST /cats/{{ cat_id }}/action 
    // { action: "sleep" } 
    }, 
}); 

請看這裏:Posting form data using .save() to pass url parameters

如果您始終想要在更新上使用自定義URL,則還可以實施同步方法以使用其他URL。例如參見:backbone.js use different urls for model save and fetch

3

有可以採取的解決這個問題的不同方法,但IMO最乾淨的是覆蓋Backbone.sync採取行動,你想要它,如果它是通用給你連接到服務器後端的行爲方式。

舉例來說,如果你希望你的模型/收藏與特定的後臺實現交互的每一個,這種方法使得有很大的意義。

這樣你就可以離開了集(或模型)代碼的其餘部分爲骨幹默認值,但它會工作,你希望它的工作方式。

例如:

// Store the default Backbone.sync so it can be referenced later 
Backbone.vanillaSync = Backbone.sync; 

// Most of this is just copy-pasted from the original Backbone.sync 
Backbone.sync = function(method, model, options) { 
    var type = methodMap[method]; 

    // Default options, unless specified. 
    _.defaults(options || (options = {}), { 
     emulateHTTP: Backbone.emulateHTTP, 
     emulateJSON: Backbone.emulateJSON 
    }); 

    // Default JSON-request options. 
    var params = {type: type, dataType: 'json'}; 

    // Ensure that we have a URL. 
    if (!options.url) { 
     params.url = _.result(model, 'url') || urlError(); 
    } 

    // START ADD YOUR LOGIC HERE TO ADD THE /action 

    // Add the action to the url 
    params.url = params.url + '/' + options.action; 

    // Remove the action from the options array so it isn't passed on 
    delete options.action; 

    // END ADD YOUR LOGIC HERE TO ADD THE /action  

    // Ensure that we have the appropriate request data. 
    if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { 
     params.contentType = 'application/json'; 
     params.data = JSON.stringify(options.attrs || model.toJSON(options)); 
    } 

    // For older servers, emulate JSON by encoding the request into an HTML-form. 
    if (options.emulateJSON) { 
     params.contentType = 'application/x-www-form-urlencoded'; 
     params.data = params.data ? {model: params.data} : {}; 
    } 

    // For older servers, emulate HTTP by mimicking the HTTP method with `_method` 
    // And an `X-HTTP-Method-Override` header. 
    if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { 
     params.type = 'POST'; 
     if (options.emulateJSON) params.data._method = type; 
     var beforeSend = options.beforeSend; 
     options.beforeSend = function(xhr) { 
     xhr.setRequestHeader('X-HTTP-Method-Override', type); 
     if (beforeSend) return beforeSend.apply(this, arguments); 
     }; 
    } 

    // Don't process data on a non-GET request. 
    if (params.type !== 'GET' && !options.emulateJSON) { 
     params.processData = false; 
    }  

    // If we're sending a `PATCH` request, and we're in an old Internet Explorer 
    // that still has ActiveX enabled by default, override jQuery to use that 
    // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8. 
    if (params.type === 'PATCH' && window.ActiveXObject && 
     !(window.external && window.external.msActiveXFilteringEnabled)) { 
     params.xhr = function() { 
     return new ActiveXObject("Microsoft.XMLHTTP"); 
     }; 
    } 

    // Make the request, allowing the user to override any Ajax options. 
    var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); 
    model.trigger('request', model, xhr, options); 
    return xhr; 
}; 

在上面的例子中,我假設你已經發送通過選項陣列的動作,如果你真的想要的靜態字/動作你可以只替換塊以:

// Add the action to the url 
params.url = params.url + '/action'; 

這應該給你最乾淨的實現,同時仍然保持你的代碼的其餘部分乾淨。

+0

我不喜歡你這樣做的方式,但我需要更多的案件逐案基礎上的東西(每個集合/模型將起到相當多的不同) - 這是否工作給予你的榜樣? – syntaqx 2013-05-14 16:26:25