2016-11-15 45 views
2

在几个视图之间共享Backbone模型是一种相当普遍的情况。尽管如此,假设这个模型是UserModel。它处理几种方法,允许用户注册或登录。几个视图的一个主干模型,谁处理fetch()?

而且当用户登录时,调用fetch来获取用户的数据。因此,该模型无法使用initialize方法中的this.fetch()自取。

它应该从哪里取?怎么样?

这是我们简单UserModel

const UserModel = Backbone.Model.extend({ 
    // get url for 'me' (ie connected user) 
    url() { 
     return app.endpoint + '/users/me/' + app.conToken; 
    }, 

    login(email, password, rememberMe, callback) { 
     … 
    }, 

    signup(email, password, firstname, lastname, callback) { 
     … 
    } 
}); 

现在让我们假设它是由两个共享:

HomeView & CartView

app.HomeView = Backbone.View.extend({ 
    template: app.tpl.home, 

    initialize() { 
     // model is passed @ instanciation 
     this.model.fetch(); 
     this.listenTo(this.model, 'sync', this.render); 
    }, 

    render() { 
     … 
    } 
}); 


app.CartView = Backbone.View.extend({ 
    template: app.tpl.cart, 

    initialize() { 
     // model is passed @ instanciation 
     this.model.fetch(); 
     this.listenTo(this.model, 'sync', this.render); 
    }, 

    render() { 
     … 
    } 
}); 

现在,如果我实例化HomeViewuserModel将是牵强。但是如果在稍后的时间点,我会立即使用CartView,这个模型会再次被提取。这使得一个无用的http请求。

基本上,模型可以在成功调用其login方法后自动获取,但用户可以到达页面或重新加载已登录的浏览器。此外,用户可以登陆任何页面,但无法说他要在CartView之前去HomeView

我看到两个选项。无论是UserModel巧妙地处理多个fetch调用,像这样:

const UserModel = Backbone.Model.extend({ 
    // get url for 'me' (ie connected user) 
    url() { 
     return app.endpoint + '/users/me/' + app.conToken; 
    }, 

    isSync() { 
     // an hour ago 
     let hourAgo = Date.now() - 3600000; 

     // data has been fetched less than an hour ago 
     if (this.fetchTime && hourAgo > this.fetchTime) return true; 
     return false; 
    }, 

    fetch() { 
     // has not already fetched data or data is older than an hour 
     if (!this.isSync()) { 
      this.fetchTime = Date.now(); 
      this.fetch(); 

      return; 
     } 

     // trigger sync without issuing any http call 
     this.trigger('sync'); 
    }, 

    … 
}); 

这样的话,我能叫this.model.fetch()多次需要,是在视图中无状态的。

或者,我可以处理一个视图层上:

app.HomeView = Backbone.View.extend({ 
    template: app.tpl.home, 

    initialize() { 
     // model is passed @ instanciation 

     // fetch model if empty 
     if (_.isEmpty(this.model.changed)) this.fetch(); 

     // render directly if already populated 
     else this.render(); 

     // render on model sync 
     this.listenTo(this.model, 'sync', this.render); 
    }, 

    render() { 
     … 
    } 
}); 

如果需要的话,Backbone's model.changed DOC参考&下划线的_.isEmpty's

哪种方式更清洁?有没有其他方法可能会错过?

回答

3

个人喜好不会覆盖fetch但不是实现一个包装的功能,如customFetch

const UserModel = Backbone.Model.extend({ 
// get url for 'me' (ie connected user) 
url() { 
    return app.endpoint + '/users/me/' + app.conToken; 
}, 

isSync() { 
    // an hour ago 
    let hourAgo = Date.now() - 3600000; 

    // data has been fetched less than an hour ago 
    if (this.fetchTime && hourAgo > this.fetchTime) return true; 
    return false; 
}, 

customFetch() { 
    // has not already fetched data or data is older than an hour 
    if (!this.isSync()) { 
     this.fetchTime = Date.now(); 
     this.fetch(); 

     return; 
    } 

    // trigger sync without issuing any http call 
    this.trigger('sync'); 
}, 

… 
}); 

您的资料将在一个循环结束的代码示例(this.fetch自称...),所以我的个人偏好是将核心主干功能包装在另一个功能中。

我甚至会自行定制我自己定制的Model,这个定制由我使用的所有型号扩展。例如:

const MyModel = Backbone.Model.extend({ 
    isSync() { 
     // an hour ago 
     let hourAgo = Date.now() - 3600000; 

     // data has been fetched less than an hour ago 
     return (this.fetchTime && hourAgo > this.fetchTime); 
    }, 
    customFetch() { 
     this.fetch(); 
    }, 
}); 

然后UserModel会覆盖customFetch和看起来像这样:

const UserModel = MyModel.extend({ 
    customFetch() { 
     // has not already fetched data or data is older than an hour 
     if (!this.isSync()) { 
      this.fetchTime = Date.now(); 
      this.fetch(); 
      return; 
     } 

     // trigger sync without issuing any http call 
     this.trigger('sync'); 
    }, 
}); 

可能不是做的最好的方式。对我个人来说,这将是它稍后阅读和扩展的简单方法。我想这customFetch将用于某些/所有模型,所以它可以适当修改。

+0

对于无限循环+1,很明显我没有测试过它:p有一个定制的基础模型听起来很棒!为什么'UserModel'重写'customFetch'虽然?它可以直接声明为基类。然后,我会在视图中调用'customFetch',在那里我只是想确保模型已经填充或直接'获取',当我需要处理最新的数据。 – Buzut

+1

@Buzut再次以我的个人喜好再次。让我们设置一个'TimeModel',它也扩展了'MyModel',这个模型我们每次都想''获取''。我宁愿在我的代码中编写'customFetch',而不是混合'customFetch'和'fetch'。你可以很容易地在'MyModel'中设置'customFetch'作为你的自定义代码。所以再次,只是这对我来说是有意义的,希望我的推理很有意义。最终它会为你写得最好,但要尽量与你的方法保持一致。 –

+0

感谢您提出明确的建议,并花时间提出全面的解答。 – Buzut

相关问题