nehmen wir an, ich habe ein Backbone-Modell und erstelle eine Instanz eines Modells wie das folgende:
var User = Backbone.Model.extend({ ... });
var John = new User({ name : 'John', age : 33 });
Ich frage mich, ob es möglich ist, wenn ich John.save()
zum Zielen auf /user/create
verwende, wenn ich John.save()
zum zweiten Mal (update/PUT) zum Zielen auf /user/update
verwende, wenn ich John.fetch()
zum Zielen auf /user/get
verwende und wenn ich John.remove()
zum Zielen auf /user/remove
verwende.
Ich weiß, dass ich jedes Mal John.url
definieren kann, bevor ich eine Methode auslöse, aber ich frage mich, ob dies automatisch passieren kann, ohne eine Backbone-Methode zu überschreiben.
Ich weiß, dass ich eine URL wie /user/handle
verwenden und die Anfrage basierend auf der Anfragemethode (GET/POST/PUT/DELETE) bearbeiten könnte, aber ich frage mich nur, ob es eine Möglichkeit gibt, eine andere URL pro Aktion in Backbone zu haben.
Vielen Dank!
Die Methoden .fetch()
, .save()
und .destroy()
on Backbone.Model
prüfen, ob das Modell .sync()
definiert ist, und wenn ja, wird es aufgerufen, andernfalls wird Backbone.sync()
aufgerufen (siehe letzte Zeilen des verknüpften Quellcodes) ).
Eine der Lösungen ist also die Implementierung der .sync()
-Methode.
Beispiel:
var User = Backbone.Model.extend({
// ...
methodToURL: {
'read': '/user/get',
'create': '/user/create',
'update': '/user/update',
'delete': '/user/remove'
},
sync: function(method, model, options) {
options = options || {};
options.url = model.methodToURL[method.toLowerCase()];
return Backbone.sync.apply(this, arguments);
}
}
Um dzejkejs solution eine Ebene weiter zu abstrahieren, können Sie die Backbone.sync
- Funktion einschließen, um das Modell nach methodenspezifischen URLs abzufragen.
function setDefaultUrlOptionByMethod(syncFunc)
return function sync (method, model, options) {
options = options || {};
if (!options.url)
options.url = _.result(model, method + 'Url'); // Let Backbone.sync handle model.url fallback value
return syncFunc.call(this, method, model, options);
}
}
Dann könnten Sie das Modell definieren mit:
var User = Backbone.Model.extend({
sync: setDefaultUrlOptionByMethod(Backbone.sync),
readUrl: '/user/get',
createUrl: '/user/create',
updateUrl: '/user/update',
deleteUrl: '/user/delete'
});
Behandeln Sie eine REST -Implementierung, die nicht spezifiziert ist oder eine Art Problemumgehung erfordert?
Verwenden Sie stattdessen die emulateHTTP
-Option, die Sie hier finden:
http://documentcloud.github.com/backbone/#Sync
Andernfalls müssen Sie wahrscheinlich nur die standardmäßige Backbone.sync
-Methode überschreiben, und Sie sind gut aufgestellt, wenn Sie wirklich verrückt werden möchten ... aber ich schlage das nicht vor. Am besten verwenden Sie einfach eine echte RESTful-Schnittstelle.
Nein, mit Backbone ist dies standardmäßig nicht möglich. Was Sie tun können, ist dem Modell hinzuzufügen, das die Modell-URL bei jedem Ereignis ändert, das der Modell-Trigger auslöst. Aber dann haben Sie immer das Problem, dass bckbone POST
verwendet, wenn das Modell zum ersten Mal gespeichert wurde, und PUT
für jeden Aufruf danach. Daher müssen Sie auch die save()
-Methode oder Backbone.sync
überschreiben.
Schließlich scheint es keine gute Idee zu sein, da dies das REST
-Muster bricht, auf dem Backbone aufgebaut ist.
Ich wurde von this solution inspiriert, bei der Sie einfach Ihren eigenen Ajax-Aufruf für die Methoden erstellen, die nicht zum Abrufen des Modells dienen. Hier ist eine abgespeckte Version davon:
var Backbone = require("backbone");
var $ = require("jquery");
var _ = require("underscore");
function _request(url, method, data, callback) {
$.ajax({
url: url,
contentType: "application/json",
dataType: "json",
type: method,
data: JSON.stringify( data ),
success: function (response) {
if ( !response.error ) {
if ( callback && _.isFunction(callback.success) ) {
callback.success(response);
}
} else {
if ( callback && _.isFunction(callback.error) ) {
callback.error(response);
}
}
},
error: function(mod, response){
if ( callback && _.isFunction(callback.error) ) {
callback.error(response);
}
}
});
}
var User = Backbone.Model.extend({
initialize: function() {
_.bindAll(this, "login", "logout", "signup");
},
login: function (data, callback) {
_request("api/auth/login", "POST", data, callback);
},
logout: function (callback) {
if (this.isLoggedIn()) {
_request("api/auth/logout", "GET", null, callback);
}
},
signup: function (data, callback) {
_request(url, "POST", data, callback);
},
url: "api/auth/user"
});
module.exports = User;
Und dann kannst du es so benutzen:
var user = new User();
// user signup
user.signup(data, {
success: function (response) {
// signup success
}
});
// user login
user.login(data, {
success: function (response) {
// login success
}
});
// user logout
user.login({
success: function (response) {
// logout success
}
});
// fetch user details
user.fetch({
success: function () {
// logged in, go to home
window.location.hash = "";
},
error: function () {
// logged out, go to signin
window.location.hash = "signin";
}
});