2016-04-01 5 views
1

Ich habe ein Modell, das von mehreren Ansichtsmodellen verwendet wird, und ich brauche einige andere Javascript-Komponenten, um das Modell zu aktualisieren, beobachtet von meinem VM. Ich habe keine Ahnung, wie man das macht, da sie im Tutorial das Modell im Viewmodel "mischen".KnockoutJS: separates Modell von Modelview

Hier ist mein Code:

var ConversationModel = { 
    conversations: ko.observableArray(), 
    open: function(userId){ 
     for(var i = 0; i < this.conversations.length; i++){ 
      if(this.conversations[i].userId == userId){ 
       return; 
      } 
     } 

     var self = this; 
     var obj = ko.observable({ 
      userId: userId 
     }); 

     self.conversations.push(obj); 

     UserManager.getUserData(userId, function(user){ 
      $.getJSON(Routes.messenger.getConversation, "receiver=" + userId, function(data){ 
       obj.receiver = user; 
       obj.data = data; 
      }); 
     }); 
    } 
}; 

function ConversationDialogViewModel() { 
    var self = this; 

    this.conversations = ko.computed(function(){ 
     return ConversationModel.conversations; 
    }); 

    console.log(this.conversations()); 

    this.conversations.subscribe(function(context){ 
     console.log(context); 
    }); 
} 
+3

Sie könnten versuchen, ein Pub/Sub-Muster mit 'ko.postbox': https://github.com/rniemeyer/knockout-postbox – cl3m

+0

Ihre mehreren Viewmodels machen mich denken, Komponenten wäre eine gute Idee. http://knockoutjs.com/documentation/component-overview.html –

Antwort

0

Sie können eine (einigermaßen) gutes Beispiel here finden, wie zu kombinieren:

  1. Komponenten
  2. Pro Seite Ansichtsmodell
  3. Zentral ServiceProviders (für B. zum Aufrufen von APIs oder zum Bereitstellen von Statusinformationen zwischen verschiedenen Komponenten)

Bitte beachten Sie, der Code ist ES2015 (neues Javascript), aber Sie können auch in Javascript schreiben, wenn Sie möchten. Das Gulp-Skript enthält das Beschriften aller HTML-Schablonen in den Komponenten, sodass sie kombiniert und als eine Datei geladen werden, aber als separate Elemente bearbeitet werden.

Ein Beispiel Komponente:

const ko = require('knockout') 
    , CentralData = require('../../service-providers/central-data') 
    , CentralState = require('../../service-providers/central-state') 
    , template = require('./template.html'); 

const viewModel = function (data) { 

    //Make service providers accessible to data-bind and templates 
    this.CentralData = CentralData; 
    this.CentralState = CentralState; 

    this.componentName = 'Component One'; 
    this.foo = ko.observable(`${this.componentName} Foo`); 
    this.bar = ko.observableArray(this.componentName.split(' ')); 
    this.barValue = ko.observable(""); 
    this.bar.push('bar'); 
    this.addToBar = (stuffForBar) => { 
     if(this.barValue().length >= 1) { 
      this.bar.push(this.barValue()); 
      CentralData.pushMoreData({firstName: this.componentName,secondName:this.barValue()}); 
     } 
    }; 
    this.CentralState.signIn(this.componentName); 
    if (CentralData.dataWeRetrieved().length < 10) { 
     var dataToPush = {firstName : this.componentName, secondName : 'Foo-Bar'}; 
     CentralData.pushMoreData(dataToPush); 
    } 
}; 
console.info('Component One Running'); 
module.exports = { 
    name: 'component-one', 
    viewModel: viewModel, 
    template: template 
}; 

und Komponentenvorlage:

<div> 
    <h1 data-bind="text: componentName"></h1> 
    <p>Foo is currently: <span data-bind="text: foo"></span></p> 
    <p>Bar is an array. It's values currently are:</p> 
    <ul data-bind="foreach: bar"> 
     <li data-bind="text: $data"></li> 
    </ul> 
    <form data-bind="submit: addToBar"> 
     <input type="text" 
       name="bar" 
       placeholder="Be witty!" 
       data-bind="attr: {id : componentName}, value : barValue" /> 
     <button type="submit">Add A Bar</button> 
    </form> 
    <h2>Central State</h2> 
    <p>The following components are currently signed in to Central State Service Provider</p> 
    <ul data-bind="foreach: CentralState.signedInComponents()"> 
     <li data-bind="text: $data"></li> 
    </ul> 
    <h2>Central Data</h2> 
    <p>The following information is available from Central Data Service Provider</p> 
    <table class="table table-bordered table-responsive table-hover"> 
     <tr> 
      <th>Component Name</th><th>Second Value</th> 
     </tr> 
     <!-- ko foreach: CentralData.dataWeRetrieved --> 
     <tr> 
      <td data-bind="text: firstName"></td><td data-bind="text: secondName"></td> 
     </tr> 
     <!-- /ko --> 
    </table> 
    <h3>End of Component One!</h3> 
</div> 

Für Ihre Zwecke können Sie die Central Zustand Anbieter und psuedo APIs ignorieren, aber Sie könnten das Modell nützlich als App wird komplizierter.