2010-12-09 15 views
3

Ich habe ein wenig mit knockoutjs gespielt und habe das folgende Beispiel produziert, genug, um durch die Idee, diese Viewmodels in Javascript zu erstellen, so dass die Ansicht in viel einfacher, deklarative Weise geschrieben werden kann, dh zuerst definieren Sie was Sie wollen beobachten, dann mit den data-bind Attribute definieren, was Sie wenn Ihre Ansichtsmodell Änderungen in gewisser Weise geschehen soll.Wie knockoutJS verwenden, um Daten auf dem Server über AJAX zu beobachten?

Aber all dies geschieht nur auf dem Client.

Wie kann ich erweitere dieses Beispiel knockoutjs zu verwenden, um den Zustand der Objekte auf dem Server zu beobachten, zum Beispiel über AJAX Anrufe?

index.htm:

<!doctype html> 
<html> 
    <title>Knockout example</title> 
    <head> 
     <script type="text/javascript" src="js/knockout-1.1.1.debug.js"></script> 
     <script type="text/javascript" src="js/main.js"></script> 
     <link rel="stylesheet" href="css/main.css" type="text/css"/> 
    </head> 
    <body> 

     <!-- FIRST AREA --> 
     <div class="infobox"> 
      <div data-bind="visible: noNamesFilled"> 
       <p>This is an example with NO names filled.</p> 
      </div> 
      <div data-bind="visible: bothNamesFilled"> 
       <p>This is an example with both names filled.</p> 
      </div> 
      <div data-bind="visible: firstNameOnlyFilled"> 
       <p>This is an example with only the first name filled.</p> 
      </div> 
      <div data-bind="visible: lastNameOnlyFilled"> 
       <p>This is an example with the last name filled but not the first name</p> 
      </div> 
     </div> 

     <!-- SECOND AREA --> 
     <p>First name: <input data-bind="value: firstName, valueUpdate:'afterkeydown'" /></p> 
     <p>Last name: <input data-bind="value: lastName, valueUpdate:'afterkeydown'" /></p> 
     <div data-bind="visible: bothNamesFilled"> 
      <h2 class="normal">Hello, <span data-bind="text: fullName"></span>.</h2> 
     </div> 
     <div data-bind="visible: firstNameOnlyFilled"> 
      <h2 class="informal">Hi there <span data-bind="text: fullName"></span>!</h2> 
     </div> 
     <div data-bind="visible: lastNameOnlyFilled"> 
      <h2 class="formal">Hello, Mr. <span data-bind="text: fullName"></span>.</h2> 
     </div> 

     <!-- THIRD AREA --> 
     <div data-bind="visible: noNamesFilled"> 
      <p><span class="bad">:-(</span> Please fill in both names.</p> 
     </div> 
     <div data-bind="visible: bothNamesFilled"> 
      <p><span class="good">:-)</span> Good job, both names are filled!</p> 
     </div> 
     <div data-bind="visible: firstNameOnlyFilled"> 
      <p><span class="ok">:-(</span> Please fill in the last name, too.</p> 
     </div> 
     <div data-bind="visible: lastNameOnlyFilled"> 
      <p><span class="ko">:-(</span> Please fill in the first name as well.</p> 
     </div> 
    </body> 
</html> 

main.css:

* { margin: 0; padding: 0} 
body { margin: 10px} 
p { margin: 10px} 
.infobox { 
    background-color: #eee; 
    width: 300px; 
    height: 100px; 
    padding: 10px; 
} 
.informal { 
    color: purple; 
    font-family: arial; 
} 
.normal { 
    color: black; 
    font-family: new courier; 
} 
.formal { 
    color: black; 
    font-size: 11pt; 
    font-family: times roman; 
    background-color: #eee; 
} 
.good { 
    width: 20px; 
    background-color: lightgreen; 
} 
.ok { 
    width: 20px; 
    background-color: yellow; 
} 
.bad { 
    width: 20px; 
    background-color: tomato; 
} 

main.js:

window.onload= function() { 

    var viewModel = { 
     firstName : ko.observable(''), 
     lastName : ko.observable('') 
    }; 
    viewModel.fullName = ko.dependentObservable(function() { 
     return viewModel.firstName() + " " + viewModel.lastName(); 
    }); 

    viewModel.bothNamesFilled = ko.dependentObservable(function() { 
     return viewModel.firstName().length > 0 && viewModel.lastName().length > 0; 
    }, this); 
    viewModel.firstNameOnlyFilled = ko.dependentObservable(function() { 
     return viewModel.firstName().length > 0 && viewModel.lastName().length == 0; 
    }, this); 
    viewModel.lastNameOnlyFilled = ko.dependentObservable(function() { 
     return viewModel.firstName().length == 0 && viewModel.lastName().length > 0; 
    }, this); 
    viewModel.noNamesFilled = ko.dependentObservable(function() { 
     return viewModel.firstName().length == 0 && viewModel.lastName().length == 0; 
    }, this); 

    ko.applyBindings(viewModel); 
} 

Antwort

4

Ich würde setTimeout verwenden, um eine Funktion aufzurufen, die JQuery verwendet, um einen $ .ajax-Aufruf auszuführen. Wenn JSON-Daten zurückgegeben werden, legen Sie diese Daten als Ihr Ansichtsmodell fest und schließlich setTimeout erneut, um die Funktion aufzurufen.

0

Hier ist ein aktualisierter Beispiel, dass in erster Linie Updates main.js mit JQuery zu arbeiten, um den Ajax-Aufruf zu tun.

Die HTML-Datei enthält Knockout 3 anstelle von 1. Der HTML enthält auch JQuery neueste die JQuery Funktionalität Arbeit zu machen.

Die js/server_data.js ist es, so dass Sie einige gültige Json Daten zu beginnen. Sie können die URL in den $ .ajax-Einstellungen in ein beliebiges serverseitiges Skript ändern, aber versuchen Sie, den Inhaltstyp auf application/json zu setzen. Zum Beispiel können PHP-Skripte den Content-Type-Header wie folgt setzen: header ('Content-type: application/json'); bevor Sie die Daten im JSON-Format ausdrucken.

neue main.html:

<!doctype html> 
<html> 
    <title>Knockout example</title> 
    <head> 
     <script type="text/javascript" src="js/knockout-3.0.0.debug.js"></script> 
     <script src="http://code.jquery.com/jquery-latest.min.js"></script> 
     <script type="text/javascript" src="js/main.js"></script> 
     <link rel="stylesheet" href="css/main.css" type="text/css"/> 
    </head> 
    <body> 

     <!-- FIRST AREA --> 
     <div class="infobox"> 
      <div data-bind="visible: noNamesFilled"> 
       <p>This is an example with NO names filled.</p> 
      </div> 
      <div data-bind="visible: bothNamesFilled"> 
       <p>This is an example with both names filled.</p> 
      </div> 
      <div data-bind="visible: firstNameOnlyFilled"> 
       <p>This is an example with only the first name filled.</p> 
      </div> 
      <div data-bind="visible: lastNameOnlyFilled"> 
       <p>This is an example with the last name filled but not the first name</p> 
      </div> 
     </div> 

     <!-- SECOND AREA --> 
     <p>First name: <input data-bind="value: firstName, valueUpdate:'afterkeydown'" /></p> 
     <p>Last name: <input data-bind="value: lastName, valueUpdate:'afterkeydown'" /></p> 
     <div data-bind="visible: bothNamesFilled"> 
      <h2 class="normal">Hello, <span data-bind="text: fullName"></span>.</h2> 
     </div> 
     <div data-bind="visible: firstNameOnlyFilled"> 
      <h2 class="informal">Hi there <span data-bind="text: fullName"></span>!</h2> 
     </div> 
     <div data-bind="visible: lastNameOnlyFilled"> 
      <h2 class="formal">Hello, Mr. <span data-bind="text: fullName"></span>.</h2> 
     </div> 

     <!-- THIRD AREA --> 
     <div data-bind="visible: noNamesFilled"> 
      <p><span class="bad">:-(</span> Please fill in both names.</p> 
     </div> 
     <div data-bind="visible: bothNamesFilled"> 
      <p><span class="good">:-)</span> Good job, both names are filled!</p> 
     </div> 
     <div data-bind="visible: firstNameOnlyFilled"> 
      <p><span class="ok">:-(</span> Please fill in the last name, too.</p> 
     </div> 
     <div data-bind="visible: lastNameOnlyFilled"> 
      <p><span class="ko">:-(</span> Please fill in the first name as well.</p> 
     </div> 
    </body> 
</html> 

js/main.js:

$(document).ready(function() { 

    var viewModel = { 
     firstName : ko.observable(''), 
     lastName : ko.observable('') 
    }; 
    viewModel.fullName = ko.dependentObservable(function() { 
     return viewModel.firstName() + " " + viewModel.lastName(); 
    }); 

    viewModel.bothNamesFilled = ko.dependentObservable(function() { 
     return viewModel.firstName().length > 0 && viewModel.lastName().length > 0; 
    }, this); 
    viewModel.firstNameOnlyFilled = ko.dependentObservable(function() { 
     return viewModel.firstName().length > 0 && viewModel.lastName().length == 0; 
    }, this); 
    viewModel.lastNameOnlyFilled = ko.dependentObservable(function() { 
     return viewModel.firstName().length == 0 && viewModel.lastName().length > 0; 
    }, this); 
    viewModel.noNamesFilled = ko.dependentObservable(function() { 
     return viewModel.firstName().length == 0 && viewModel.lastName().length == 0; 
    }, this); 

    ko.applyBindings(viewModel); 

    // send request to the server to download the server's model information. 
    $.ajax(
    { 
     'url': 'js/server_data.js', 
     'dataType': 'json', 
     'method': 'post', 
     'error': function(jqXHR, textStatus, errorThrown) 
     { 
      // error callback in case you play with this code and run into trouble. 
      alert('There was a problem handling the ajax request. The error information is: jqXHR: ' 
      +jqXHR+", textStatus: "+textStatus+", errorThrown: "+errorThrown); 
     }, 
     'success': function(data) 
     { 
      // when it is downloaded and parsed to create the "data" parameter, update the viewModel. 
      viewModel.firstName(data.firstName); 
      viewModel.lastName(data.lastName); 
     } 
    } 
    ); 
} 
); 

js/server_data.js dynamisch generierten Daten darstellt, die aus einer Datenbank sein könnte:

{ 
    "firstName": "John", 
    "lastName": "Doe" 
} 

jsteve hat die richtige allgemeine Idee, aber verwenden Sie nicht setTimeout, wenn Sie nur die Daten beim Laden der Seite herunterladen möchten s. Verwenden Sie stattdessen den Dokument-Ready-Callback von JQuery und den Ajax-Success-Callback von JQuery, damit die Dinge genau dann ablaufen, wenn Sie es möchten.

Wenn Sie ständig auf Änderungen an Daten im Server reagieren und darauf reagieren möchten, sollten Sie lange Pollertechniken untersuchen. Ein Long-Poller ist effizienter und präziser als ein beschäftigtes Warten, das eine häufige neue Anforderung an den Server erfordert.