Knockout JS 示例

Posted Jeff Xiong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Knockout JS 示例相关的知识,希望对你有一定的参考价值。

五个小例子,来自Knockout JS官方网站。



//tutorial 1
//following codes uses to demonstrate observable values and target bound ways especially method bound

<!-- This is a *view* - html markup that defines the appearance of your UI -->

<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>

<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>

<p>Full name: <strong data-bind="text: fullName"></strong></p>

<button data-bind="click: capitalizeLastName">Go caps</button>


// This is a simple *viewmodel* - javascript that defines the data and behavior of your UI
function AppViewModel() 
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");

    this.fullName = ko.computed(function() 
        return this.firstName() + " " + this.lastName();    
    , this);

    this.capitalizeLastName = function() 
        var currentVal = this.lastName();        // Read the current value
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    ;    


// Activates knockout.js
ko.applyBindings(new AppViewModel());










//tutorial 2
//this demo shows how to use observable array to bind html elements and how to define model

<h2>Your seat reservations (<span data-bind="text: seats().length"></span>)</h2>

<table>
    <thead><tr>
        <th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th>
    </tr></thead>
    <tbody data-bind="foreach: seats">
        <tr>
            <td><input data-bind="value: name" /></td>
            <td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td>
            <td data-bind="text: formattedPrice"></td>
            <td><a href="#" data-bind="click: $root.removeSeat">Remove</a></td>
        </tr>    
    </tbody>
</table>

<button data-bind="click: addSeat, enable: seats().length < 5">Reserve another seat</button>

<h3 data-bind="visible: totalSurcharge() > 0">
    Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span>
</h3>


// Class to represent a row in the seat reservations grid
function SeatReservation(name, initialMeal) 
    var self = this;
    self.name = name;
    self.meal = ko.observable(initialMeal);

    self.formattedPrice = ko.computed(function() 
        var price = self.meal().price;
        return price ? "$" + price.toFixed(2) : "None";        
    );    


// Overall viewmodel for this screen, along with initial state
function ReservationsViewModel() 
    var self = this;

    // Non-editable catalog data - would come from the server
    self.availableMeals = [
         mealName: "Standard (sandwich)", price: 0 ,
         mealName: "Premium (lobster)", price: 34.95 ,
         mealName: "Ultimate (whole zebra)", price: 290 
    ];    

    // Editable data
    self.seats = ko.observableArray([
        new SeatReservation("Steve", self.availableMeals[0]),
        new SeatReservation("Bert", self.availableMeals[0])
    ]);

    // Computed data
    self.totalSurcharge = ko.computed(function() 
       var total = 0;
       for (var i = 0; i < self.seats().length; i++)
           total += self.seats()[i].meal().price;
       return total;
    );    

    // Operations
    self.addSeat = function() 
        self.seats.push(new SeatReservation("", self.availableMeals[0]));
    
    self.removeSeat = function(seat)  self.seats.remove(seat) 


ko.applyBindings(new ReservationsViewModel());





//tutorial 3 
//this demo shows how to use ajax to get data and update observable arrary

<script src="/scripts/lib/sammy.js" type="text/javascript"></script>

<!-- Folders -->
<ul class="folders" data-bind="foreach: folders">
    <li data-bind="text: $data, 
                   css:  selected: $data == $root.chosenFolderId() ,
                   click: $root.goToFolder"></li>
</ul>

<!-- Mails grid -->
<table class="mails" data-bind="with: chosenFolderData">
    <thead><tr><th>From</th><th>To</th><th>Subject</th><th>Date</th></tr></thead>
    <tbody data-bind="foreach: mails">
        <tr data-bind="click: $root.goToMail">
            <td data-bind="text: from"></td>
            <td data-bind="text: to"></td>
            <td data-bind="text: subject"></td>
            <td data-bind="text: date"></td>
        </tr>     
    </tbody>
</table>

<!-- Chosen mail -->
<div class="viewMail" data-bind="with: chosenMailData">
    <div class="mailInfo">
        <h1 data-bind="text: subject"></h1>
        <p><label>From</label>: <span data-bind="text: from"></span></p>
        <p><label>To</label>: <span data-bind="text: to"></span></p>
        <p><label>Date</label>: <span data-bind="text: date"></span></p>
    </div>
    <p class="message" data-bind="html: messageContent" />
</div>


function WebmailViewModel() 
    // Data
    var self = this;
    self.folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
    self.chosenFolderId = ko.observable();
    self.chosenFolderData = ko.observable();
    self.chosenMailData = ko.observable();

    // Behaviours    
    self.goToFolder = function(folder)  location.hash = folder ;
    self.goToMail = function(mail)  location.hash = mail.folder + '/' + mail.id ;

    // Client-side routes    
    Sammy(function() 
        this.get('#:folder', function() 
            self.chosenFolderId(this.params.folder);
            self.chosenMailData(null);
            $.get("/mail",  folder: this.params.folder , self.chosenFolderData);
        );

        this.get('#:folder/:mailId', function() 
            self.chosenFolderId(this.params.folder);
            self.chosenFolderData(null);
            $.get("/mail",  mailId: this.params.mailId , self.chosenMailData);
        );
    
        this.get('', function()  this.app.runRoute('get', '#Inbox') );
    ).run();    
;

ko.applyBindings(new WebmailViewModel());


//tutorial 4 
// shows how to define custom binding target


<h3 data-bind="text: question"></h3>
<p>Please distribute <b data-bind="text: pointsBudget"></b> points between the following options.</p>

<table>
    <thead><tr><th>Option</th><th>Importance</th></tr></thead>
    <tbody data-bind="foreach: answers">
        <tr>
            <td data-bind="text: answerText"></td>
            <td data-bind="starRating: points"></td>
        </tr>    
    </tbody>
</table>

<h3 data-bind="fadeVisible: pointsUsed() > pointsBudget">You've used too many points! Please remove some.</h3>
<p>You've got <b data-bind="text: pointsBudget - pointsUsed()"></b> points left to use.</p>
<button data-bind="jqButton:  enable: pointsUsed() <= pointsBudget , click: save">Finished</button>


// ----------------------------------------------------------------------------
// Reusable bindings - ideally kept in a separate file

ko.bindingHandlers.fadeVisible = 
    init: function(element, valueAccessor) 
        // Start visible/invisible according to initial value
        var shouldDisplay = valueAccessor();
        $(element).toggle(shouldDisplay);
    ,
    update: function(element, valueAccessor) 
        // On update, fade in/out
        var shouldDisplay = valueAccessor();
        shouldDisplay ? $(element).fadeIn() : $(element).fadeOut();
     
;

ko.bindingHandlers.jqButton = 
    init: function(element) 
       $(element).button(); // Turns the element into a jQuery UI button
    ,
    update: function(element, valueAccessor) 
        var currentValue = valueAccessor();
        // Here we just update the "disabled" state, but you could update other properties too
        $(element).button("option", "disabled", currentValue.enable === false);
        
;

ko.bindingHandlers.starRating = 
    init: function(element, valueAccessor) 
        $(element).addClass("starRating");
        for (var i = 0; i < 5; i++)
           $("<span>").appendTo(element);
       
        // Handle mouse events on the stars
        $("span", element).each(function(index) 
            $(this).hover(
                function()  $(this).prevAll().add(this).addClass("hoverChosen") , 
                function()  $(this).prevAll().add(this).removeClass("hoverChosen")                 
            ).click(function()  
                var observable = valueAccessor();  // Get the associated observable
                observable(index+1);               // Write the new rating to it
            );
        );            
    ,
    update: function(element, valueAccessor) 
        // Give the first x stars the "chosen" class, where x <= rating
        var observable = valueAccessor();
        $("span", element).each(function(index) 
            $(this).toggleClass("chosen", index < observable());
        );
        
;

// ----------------------------------------------------------------------------
// Page viewmodel

function Answer(text)  this.answerText = text; this.points = ko.observable(1); 

function SurveyViewModel(question, pointsBudget, answers) 
    this.question = question;
    this.pointsBudget = pointsBudget;
    this.answers = $.map(answers, function(text)  return new Answer(text) );
    this.save = function()  alert('To do') ;
           
    this.pointsUsed = ko.computed(function() 
        var total = 0;
        for (var i = 0; i < this.answers.length; i++)
            total += this.answers[i].points();
        return total;        
    , this);


ko.applyBindings(new SurveyViewModel("Which factors affect your technology choices?", 10, [
   "Functionality, compatibility, pricing - all that boring stuff",
   "How often it is mentioned on Hacker News",    
   "Number of gradients/dropshadows on project homepage",        
   "Totally believable testimonials on project homepage"
]));


//tutorial 5
//shows how to communicate with server side and how to delete items using deleted flag

<h3>Tasks</h3>

<form data-bind="submit: addTask">
    Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" />
    <button type="submit">Add</button>
</form>

<ul data-bind="foreach: tasks, visible: tasks().length > 0">
    <li>
        <input type="checkbox" data-bind="checked: isDone" />
        <input data-bind="value: title, disable: isDone" />
        <a href="#" data-bind="click: $parent.removeTask">Delete</a>
    </li> 
</ul>

You have <b data-bind="text: incompleteTasks().length"> </b> incomplete task(s)
<span data-bind="visible: incompleteTasks().length == 0"> - it's beer time!</span>

<button data-bind="click: save">Save</button>

function Task(data) 
    this.title = ko.observable(data.title);
    this.isDone = ko.observable(data.isDone);


function TaskListViewModel() 
    // Data
    var self = this;
    self.tasks = ko.observableArray([]);
    self.newTaskText = ko.observable();
    self.incompleteTasks = ko.computed(function() 
        return ko.utils.arrayFilter(self.tasks(), function(task)  return !task.isDone() && !task._destroy );
    );

    // Operations
    self.addTask = function() 
        self.tasks.push(new Task( title: this.newTaskText() ));
        self.newTaskText("");
    ;
    self.removeTask = function(task)  self.tasks.destroy(task) ;
    self.save = function() 
        $.ajax("/tasks", 
            data: ko.toJSON( tasks: self.tasks ),
            type: "post", contentType: "application/json",
            success: function(result)  alert(result) 
        );
    ;

    // Load initial state from server, convert it to Task instances, then populate self.tasks
    $.getJSON("/tasks", function(allData) 
        var mappedTasks = $.map(allData, function(item)  return new Task(item) );
        self.tasks(mappedTasks);
    );    


ko.applyBindings(new TaskListViewModel());

以上是关于Knockout JS 示例的主要内容,如果未能解决你的问题,请参考以下文章

Knockout.js 中的数据绑定

在 knockout.js 视图模型中使用 `var self = this` 有啥好处 [重复]

如何使用 Knockout.js 在特定位置将项目添加/插入到 ObservableArray

knockout.js 完成渲染所有元素后的成功回调

如何在knock.js中指定绑定上下文,就像在knockout.js和WPF中一样

knockout.js入门