2016-11-15 37 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

相關問題