2016-11-15 4 views
2

Наличие модели Backbone, разделенной между несколькими видами, является довольно распространенной ситуацией. Тем не менее, скажем, эта модель - UserModel. Он обрабатывает несколько методов, позволяя пользователю зарегистрироваться или войти, например.Одна модель Backbone для нескольких видов, которая обрабатывает выборку()?

И когда пользователь регистрируется, вызывается функция fetch для получения данных пользователя. Поэтому модель не может получить this.fetch() в своем методе initialize.

Куда изволите его? Как?

Это наш простой 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() { 
     … 
    } 
}); 

Теперь, если я создании экземпляра HomeView, userModel будет неправдоподобным. Но если на более позднем этапе я создам CartView, эта же модель будет снова загружена. И это делает бесполезный HTTP-запрос.

В принципе, модель могла бы забрать istself после успешного вызова своего метода login, но пользователь может прийти на страницу или перезагрузить свой браузер, уже входящий в систему. Кроме того, пользователь может приземлиться на любую страницу, нет никакого способа скажем, он собирается HomeView до CartView.

Есть два варианта, которые я вижу. Либо 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 документ ссылка & Подчеркивание-х _.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' в представлениях, где я просто хочу убедиться, что модель заполнена или непосредственно' fetch', когда мне нужно иметь дело с самыми современными данными. – Buzut

+1

@Buzut снова снова мое личное предпочтение. Давайте установим, что у нас был «TimeModel», который также расширяет «MyModel», эту модель мы хотели бы «получать» каждый раз. Я бы предпочел писать 'customFetch' везде в моем коде, а не смешивать' customFetch' и 'fetch'. Вы легко можете установить 'customFetch' в' MyModel' как свой собственный код. Итак, опять же, именно так оно и имеет смысл для меня, надеюсь, мои рассуждения имеют смысл. В конечном счете это то, что лучше всего подходит для вас, но старайтесь соответствовать вашему подходу. –

+0

Спасибо за то, что поняли, и за то, что нашли время, чтобы предложить исчерпывающий ответ. – Buzut