backbone.js change url parameter of a Model and fetch does not update data fetched

后端 未结 4 504
再見小時候
再見小時候 2021-02-04 10:28

I have the following Model:

window.MyModel = Backbone.Model.extend({
     initialize: function(props){
          this.url = props.url;
     } 

     parse: funct         


        
相关标签:
4条回答
  • 2021-02-04 10:28

    Well the answer here is that you want to do:

    mod.url = '/some/other/url'
    

    The URL isn't part of the instance of the model itself, but rather an attribute of the MyModel object that you're creating your model instance from. Therefore, you'd just set it like it was an normal JavaScript object property. set is used only when the data you're setting (or conversely getting with get) is actually an attribute of the data you want to send/receive from the server.

    But why you're changing the URL is the question we should be asking. The idea behind Backbone's model/collection system is that you speak to a REST endpoint and each model has a corresponding endpoint.

    Like you've got a blog and that blog has an "entry" object which is available at:

    /rest/entry/
    

    And you've got a Backbone model for Entry:

    Entry = Backbone.Model.extend({urlBase: '/rest/entry'});
    

    Now when you save or fetch Backbone knows how this works.

    So like you're making a new model:

    e = new Entry();
    e.set({title: "my blog rulez", body: "this is the best blog evar!!!!1!!"});
    e.save();
    

    This would then make Backbone do an HTTP POST request to /rest/entry with the body:

    {
      "title": "my blog rulez",
      "body": "this is the best blog evar!!!!1!!"
    }
    

    (When you do your mod.set({url: '/some/other/url'}); you're actually adding a field called url to the dataset, so the server would send "url": "/some/other/url" as part of that JSON POST body above:

    {
      "title": "my blog rulez",
      "body": "this is the best blog evar!!!!1!!",
      "url": "/some/other/url" 
    }
    

    The server would then respond with an HTTP 200 (or 201) response with the same model, only with, like, say, and ID attached:

    {
      "id": 1,
      "title": "my blog rulez",
      "body": "this is the best blog evar!!!!1!!"
    }
    

    And that's not what you're looking for, right?)

    Now you've got this model and it's got an ID. This means if you change it:

    e.set('title', 'my blog is actually just ok');
    e.save()
    

    Backbone now makes an HTTP PUT request on /rest/entry/1 to update the resource on the server.

    The server sees that you're talking about ID 1 on the /rest/entry/ endpoint, so knows to update an existing record (and send back an HTTP 200).

    TL;DR

    Don't change the URL, Backbone will. Make a new model for a new piece of data.

    0 讨论(0)
  • 2021-02-04 10:35

    You can set url as option in fetch function, like this:

    var mod = new MyModel();
    mod.fetch({
       url: '/some/other/url',
       data: {}
    });
    
    0 讨论(0)
  • 2021-02-04 10:43
    model.urlRoot = "/your/url"
    

    OR

    model.urlRoot = function(){ return "/your/url"; }
    

    OR

    model.url = "/your/url"
    

    OR

    model.url = function(){ return "/your/url"; }
    

    Default 'url' property of a Backbone.Model object is as below. Backbone.js doc says:

    Default URL for the model's representation on the server -- if you're using Backbone's restful methods, override this to change the endpoint that will be called.

    url: function() {
      var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError();
      if (this.isNew()) return base;
      return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);
    },
    

    Clearly, It first gets the value of urlRoot, if not available, it will look at the url of the collection to which model belongs. By defining urlRoot instead of url has an advantage of falling back to collection url in case urlRoot is null.

    0 讨论(0)
  • 2021-02-04 10:48

    After have understood the @tkone 's explanation...

    If you still want to have a dynamic Model.url you always can delay its construction to run time, try this:

    window.MyModel = Backbone.Model.extend({
      url: function(){
        return this.instanceUrl;
      },
      initialize: function(props){
        this.instanceUrl = props.url;
      } 
    }
    
    0 讨论(0)
提交回复
热议问题