【问题标题】:Backbone.js Model different url for create and update?Backbone.js 模型创建和更新的不同 url?
【发布时间】:2012-02-02 15:23:46
【问题描述】:

假设我有一个主干模型,我创建了一个这样的模型实例:

var User = Backbone.Model.extend({ ... });
var John = new User({ name : 'John', age : 33 });

我想知道当我使用John.save() 来定位/user/create 当我第二次使用John.save() 来定位/user/update 时,我是否可以使用John.fetch() 来定位/user/get当我使用John.remove() 定位/user/remove

我知道我可以在每次触发任何方法之前定义John.url,但我想知道它是否可以在不覆盖任何 Backbone 方法的情况下自动发生。

我知道我可以使用像 /user/handle 这样的 URL 并根据请求方法 (GET/POST/PUT/DELETE) 处理请求,但我只是想知道是否有办法让每个操作都有不同的 url骨干。

谢谢!

【问题讨论】:

    标签: rest backbone.js


    【解决方案1】:

    不,默认情况下您不能使用主干执行此操作。您可以添加到模型中,该模型将在模型触发的每个事件上更改模型 url。但是你总是会遇到问题,bckbone 将在第一次保存模型时使用POST 添加,然后在每次调用之后使用PUT。因此,您还需要覆盖save() 方法或Backbone.sync

    毕竟这样做似乎不是一个好主意,因为它破坏了 Backbone 所基于的 REST 模式。

    【讨论】:

    • 感谢安德里亚的回复 :)
    【解决方案2】:

    您是否正在处理不符合规范或需要某种解决方法的 REST 实现?

    请考虑使用此处的emulateHTTP 选项:

    http://documentcloud.github.com/backbone/#Sync

    否则,您可能只需要覆盖默认的Backbone.sync 方法,如果您想对此感到真正的疯狂,您会很高兴......但我不建议这样做。最好只使用真正的 RESTful 接口。

    【讨论】:

    • 感谢您的回复 :) 我会考虑遵循 REST 实现而不是“到处乱搞” :)
    【解决方案3】:

    Backbone.Model 上的 .fetch().save().destroy() 方法正在检查模型是否定义了 .sync(),如果是,它将被调用,否则将调用 Backbone.sync()(参见链接源代码)。

    所以解决方案之一是实现.sync() 方法。

    示例:

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

    【讨论】:

    • 很好的解决方案。您应该使用options || (options = {}); 而不是options = options || {};,以避免不必要的重新分配。
    • @BrianNickel 我同意您的代码更加优化,但我有点保留将其包含在答案中,因为 JSLint/JSHint 工具将其标记为问题,在我看来这有点困难阅读......但我给了你+1,因为它值得关注:)。
    • 非常感谢 dzejkej 指出它将首先查看模型的同步方法,我完全错过了 :) 感谢@Brian Nickel 也指出了这一点 :)
    • @dzejkej,确保从同步返回结果值(否则这会破坏延迟调用模式)同步:函数(方法,模型,选项){选项=选项|| {}; options.url = model.methodToURL[method.toLowerCase()];返回 Backbone.sync(方法、模型、选项); }
    • 很好的解决方案!了解了这个细节。
    【解决方案4】:

    为了进一步抽象 dzejkej 的解决方案,您可以包装 Backbone.sync 函数来查询模型以获取 特定于方法的 URL

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

    然后你可以定义模型:

    var User = Backbone.Model.extend({
        sync: setDefaultUrlOptionByMethod(Backbone.sync),
        readUrl: '/user/get',
        createUrl: '/user/create',
        updateUrl: '/user/update',
        deleteUrl: '/user/delete'
    });
    

    【讨论】:

      【解决方案5】:

      我受到this 解决方案的启发,您只需为不用于获取模型的方法创建自己的 ajax 调用。这是它的精简版:

      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;
      

      然后你可以像这样使用它:

      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";
        }
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-24
        相关资源
        最近更新 更多