Как использовать KnockoutJS для наблюдения данных на сервере через AJAX? - PullRequest
3 голосов
/ 09 декабря 2010

Я немного поиграл с knockoutjs и подготовил следующий пример, которого достаточно, чтобы воодушевиться идеей построения этих моделей представления в javascript, чтобы представление могло быть написано гораздо более простым, декларативным способом То есть сначала вы определяете , что вы хотите наблюдать , а затем с помощью атрибутов data-bind определяете , что вы хотите произойти , когда ваша модель представления изменяется определенным образом.

Но все это происходит только на клиенте.

Как можно расширить этот пример, чтобы использовать knockoutjs для наблюдения за состоянием объектов на сервере, например, через AJAX звонки?

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);
}

Ответы [ 2 ]

4 голосов
/ 13 декабря 2010

Я бы использовал setTimeout для вызова функции, которая использует JQuery для вызова $ .ajax.Когда он возвращает данные JSON, установите эти данные в качестве модели представления и, наконец, снова установите setTimeout для вызова функции.

0 голосов
/ 07 ноября 2013

Вот обновленный пример, который в основном обновляет main.js для работы с JQuery для выполнения вызова ajax.

HTML-файл включает в себя Knockout 3 вместо 1. HTML-файл также содержит последнюю версию JQuery для обеспечения работоспособности JQuery.

Файл js / server_data.js существует, поэтому у вас есть некоторые допустимые данные json для начала. Вы можете изменить URL-адрес в настройках $ .ajax на любой имеющийся у вас серверный скрипт, но попытайтесь установить его тип контента на application / json. Например, PHP-скрипты могут устанавливать заголовок типа контента, например: header ('Content-type: application / json'); перед печатью данных в формате JSON.

новый 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, представляющий динамически генерируемые данные, которые могут быть из базы данных:

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

jsteve имеет правильную общую идею, но не используйте setTimeout, если вы просто хотите загрузить данные при загрузке страницы. Вместо этого используйте обратный вызов готовности документа JQuery и обратный вызов успеха JQuery ajax, чтобы все работало именно тогда, когда вы этого хотите.

Если вы хотите постоянно прослушивать и реагировать на изменения данных на сервере, изучите методы длинных опросов. Длинный опросчик более эффективен и точнее рассчитан, чем занятое ожидание, которое требует частого нового запроса к серверу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...