Google Code Prettify

[MVVM]knockoutjs

官網: http://knockoutjs.com/index.html
下載: http://knockoutjs.com/downloads/index.html
互動式教程: http://learn.knockoutjs.com/#/?tutorial=intro
示例: http://knockoutjs.com/examples/
文件: http://knockoutjs.com/documentation/introduction.html



knockout.js
可幫助您使用 Model-View-ViewModel(MVVM)模式簡化動態 JavaScript UI。


Knockout是一個JavaScript庫,可幫助您使用乾淨的底層數據模型創建豐富的響應式顯示和編輯器用戶界面。 只要您有動態更新的UI部分(例如,根據用戶的操作或外部數據源更改而更改),KO可以幫助您更簡單,更可維護地實施它。


優雅的依賴關係跟踪 
在數據模型發生變化時自動更新UI的正確部分

聲明性綁定
將UI的各個部分連接到數據模型的簡單明了的方法。 您可以使用任意嵌套的綁定上下文輕鬆構建複雜的動態UI

簡單可擴展
將自定義行為實現為新的聲明性綁定,以便在幾行代碼中輕鬆重用。

純JavaScript庫 
適用於任何服務器或客戶端技術,可以添加到現有Web應用程序之上,而無需進行重大架構更改

緊湊 
gzipping 後約 13kb

適用於任何主流瀏覽器
IE 6 +,Firefox 2 +,Chrome,Safari,Edge等

全面的規範套件
開發的BDD風格,意味著它可以在新的瀏覽器和平台上輕鬆驗證其正確的功能


熟悉 Ruby on Rails,ASP.NET MVC 或其他 MV * 技術的開發人員可能會將 MVVM 視為具有聲明性語法的 MVC 實時形式。 在另一種意義上,您可以將 KO 視為製作用於編輯 JSON 數據的 U I 實作方法。



Bower

Knockout 可通過 Bower 包管理器獲得。 在 http://bower.io 上了解有關使用和安裝 Bower 的更多信息。 要將 Knockout 添加到您的應用程序,您可以運行:

     bower install knockoutckoutb



安裝

只需在 HTML 頁面的某處使用 <script> 標記引用 JavaScript 文件即可。 例如,

     <script type='text/javascript' src='knockout-3.4.2.js'></script>

你可以更新 src 屬性以匹配下載文件的位置。

接下來,如果您是Knockout的新手,請開始使用交互式教程,查看一些實時示例,或深入了解有關可觀察對象的文檔。



第三方 CDN 引用

為了給您的用戶提供最快的下載速度,您可以考慮在第三方 CDN 上引用 knockout.js:

CDNJS :
     https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js

Microsoft Ajax CDN :
     http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.4.2.js





使用observable創建視圖模型

Knockout 三個核心構建功能:
  1. 可觀察量和依賴性跟踪
  2. 聲明性綁定
  3. 模板


在此頁面上,您將了解這三個中的第一個。 但在此之前,讓我們來看看MVVM模式和視圖模型的概念。


Model-View-View Model (MVVM) 是用於構建用戶界面的設計模式。 它描述瞭如何通過將可能複雜的 UI 分為三個部分來簡化它們:


模型 (Model):
應用程序的存儲數據。此數據表示業務域中的對象和操作(例如,可以執行匯款的銀行帳戶),並且獨立於任何 UI。使用 KO 時,通常會對某些服務器端代碼進行 Ajax 調用,以讀取和寫入此存儲的模型數據。

視圖模型 (View Model):
UI 上數據和操作的純代碼表示。例如,如果要實現列表編輯器,則視圖模型將是一個包含項列表的對象,並公開添加和刪除項的方法。

請注意
這不是 UI 本身:它沒有按鈕或顯示樣式的任何概念。它也不是持久數據模型 - 它保存用戶正在使用的未保存數據。使用 KO 時,您的視圖模型是純 JavaScript objects,不了解 HTML 。以這種方式保持視圖模型的抽象使其保持簡單,因此您可以管理更複雜的行為而不會丟失。

視圖(View):
表示視圖模型狀態的可見交互式 UI 。它顯示來自視圖模型的信息,將命令發送到視圖模型(例如,當用戶單擊按鈕時),並且每當視圖模型的狀態改變時更新。

使用KO時,您的視圖只是具有聲明性綁定的 HTML 文檔,以將其鏈接到視圖模型。或者,您可以使用視圖模型中的數據生成 HTML 的模板。


View Model
var myViewModel = {
    personName: 'Bob',
    personAge: 123
};

ko.applyBindings(myViewModel);


View
The name is <span data-bind="text: personName"></span>




applyBindings 的參數:
第一個參數是 View Model 物件與它激活的聲明性綁定
第二個參數(可選)定義要搜索數據綁定屬性的文檔的哪個部分。 如果您希望擁有多個視圖模型並將每個視圖模型與頁面的不同區域相關聯,這將非常有用。

例:
ko.applyBindings(myViewModel, document.getElementById('someElementId'))



好的,您已經了解瞭如何創建基本視圖模型以及如何使用綁定顯示其中一個屬性。 但 KO 的一個主要優點是它可以在視圖模型更改時自動更新 UI



KO 如何知道視圖模型的哪些部分發生變化?

答:
您需要將模型屬性聲明為可觀察對象,因為這些是特殊的 JavaScript 對象,可以通知訂閱者有關更改的信息,並且可以自動檢測依賴關係。

例如,重寫前面的視圖模型對象,如下所示:

var myViewModel = {
    personName: ko.observable('Bob'),
    personAge: ko.observable(123)
};



並非所有瀏覽器都支持 JavaScript getter 和 setter(* cough * IE * cough *),因此為了兼容性, ko.observable 對象實際上是函數。

要讀取 observable 的當前值,只需調用沒有參數的 observable 。 在此示例中,myViewModel.personName() 將返回 'Bob', myViewModel.personAge() 返回 123。

要向 observable 寫入新值,請調用 observable 並將新值作為參數傳遞。 例如,調用 myViewModel.personName('Mary') 會將名稱值更改為 “Mary”。

要將值寫入 View objects 上的多個可觀察屬性,可以使用鏈接語法。 例如,myViewModel.personName('Mary').personAge(50) 會將名稱值更改為 “Mary”,將年齡值更改為50。


可觀察的整個觀點是它們可以被觀察到,即,其他代碼可以說它希望被通知變化。 這就是 KO的 許多內置綁定在內部所做的事情。 因此,當您編寫 data-bind =“text:personName” 時,文本綁定會自動註冊,以便在 personName 更改時得到通知。

通過調用 myViewModel.personName('Mary') 將名稱值更改為“Mary”時,文本綁定將自動更新關聯 DOM 元素的文本內容。 這就是 View Model 的變更會自動更新到 View。



例:

View Model
var myViewModel = {
    personName: ko.observable('Bob'),
    personAge: ko.observable(123),
};

ko.applyBindings(myViewModel );

if (myViewModel.personName() == 'Bob')
{
    myViewModel.personName('Morse').personAge(50);
}


View
The name is <span data-bind="text: personName"></span>.
age is <span data-bind="text: personAge"></span>


Result
The name is Morse. age is 50



訂閱subscribe observables

在一般情況下您通常不需要手動設置訂閱,因此初學者應跳過此部分。

對於高級用戶,如果要註冊自己的訂閱以通知可觀察對象的更改,則可以調用其訂閱功能。 例如:


myViewModel.personName.subscribe(function(newValue) {
    alert("The person's new name is " + newValue);
});

訂閱功能是 KO 在內部工作的部分。 大多數情況下,您不需要使用它,因為內置綁定和模板系統負責管理訂閱。



subscribe 函數接受三個參數:
   callback 是在通知發生時調用的函數
   target(可選)在回調函數中定義 this 的值
   event(可選;默認為“change”)是事件的名稱 收到通知。

如果您願意,也可以終止訂閱:首先將返回值捕獲為變量,然後可以調用其 dispose 函數,例如:

var subscription = myViewModel.personName.subscribe(function(newValue) { /* do stuff */ });
// ...then later...
subscription.dispose(); // I no longer want notifications


如果您希望在即將更改之前收到可觀察值的通知,您可以訂閱beforeChange事件。 例如:

myViewModel.personName.subscribe(function(oldValue) {
    alert("The person's previous name is " + oldValue);
}, null, "beforeChange");

注意:Knockout 不保證 beforeChange 和 change 事件成對出現,因為代碼的其他部分可能會單獨引發任一事件。 如果您需要跟踪可觀察量的先前值,則可以使用訂閱來捕獲和跟踪它。


強制觀察者始終通知訂閱者
當寫入包含原始值(數字,字符串,布爾值或空值)的 observable 時,通常只有在實際更改值時才會通知 observable 的依賴項。 但是,可以使用內置的通知擴展器來確保在寫入時始終通知可觀察的訂戶,即使該值是相同的。 您可以將擴展器應用於這樣的可觀察量:

myViewModel.personName.extend({ notify: 'always' });


延遲和/或禁止更改通知
通常情況下,一個觀察者一改變就立即通知其訂戶。 但是,如果反復更改observable或觸發昂貴的更新,則可以通過限製或延遲observable的更改通知來獲得更好的性能。 這是使用rateLimit擴展器完成的,如下所示:

myViewModel.personName.extend({ rateLimit: 50 });





使用可觀察數組

如果要檢測並響應一個對象的更改,則可以使用 observable。 如果要檢測並響應事物集合的更改,請使用 observableArray 。 這在您正在顯示或編輯多個值並且需要重複的 UI 部分顯示和消失時添加和刪除項目的許多情況下都很有用。

var myObservableArray = ko.observableArray();    // Initially an empty array
myObservableArray.push('Some value');            // Adds the value and notifies observers

要了解如何將observableArray綁定到UI並讓用戶修改它,請參閱簡單列表示例

關鍵點:
observableArray 跟踪數組中的對象,而不是這些對象的狀態,簡單地將對象放入 observableArray 並不會使該對象的所有屬性本身都可觀察到。 當然,如果您願意,您可以觀察這些屬性,但這是一個獨立的選擇。 observableArray 只跟踪它所擁有的對象,並在添加或刪除對象時通知偵聽器。


預先設定 observableArray
如果希望您的可觀察數組不是空的,而是包含一些初始項,請將這些項作為數組傳遞給構造函數。 例如,

// This observable array initially contains three objects
var anotherObservableArray = ko.observableArray([
    { name: "Bungle", type: "Bear" },
    { name: "George", type: "Hippo" },
    { name: "Zippy", type: "Unknown" }
]);


從 observableArray 中讀取信息
在幕後, observableArray 實際上是一個可觀察的,其值是一個數組(另外, observableArray 添加了下面描述的一些附加功能)。 因此,您可以通過調用 observableArray 作為沒有參數的函數來獲取底層 JavaScript 數組,就像任何其他可觀察對像一樣。 然後,您可以從該基礎數組中讀取信息。 例如,

alert('The length of the array is ' + myObservableArray().length);
alert('The first element is ' + myObservableArray()[0]);


從技術上講,您可以使用任何本機 JavaScript 數組函數來操作該底層數組,但通常有更好的替代方案。 KO 的 observableArray 具有自己的等效功能,它們更有用,因為:

它們適用於所有目標瀏覽器。 (例如,本機 JavaScript indexOf 函數在 IE 8 或更早版本上不起作用,但 KO 的 indexOf 無處不在。)

對於修改數組內容的函數,例如 push 和 splice ,KO 的方法會自動觸發依賴關係跟踪機制,以便所有已註冊的偵聽器都會收到更改通知,並且 UI 會自動更新,這意味著使用之間存在顯著差異 KO 的方法(即 observableArray.push(...))和 JavaScript 本機數組方法(即observableArray().push(...))作為後者不向數組的訂閱者發送任何通知,其內容有改變。


本頁的其餘部分描述了 observableArray 用於讀取和寫入數組信息的函數



indexOf
indexOf 函數返回與您的參數相等的第一個數組項的索引。 例如,myObservableArray.indexOf('Blah') 將返回第一個數組條目的從零開始的索引,該索引等於 Blah ,如果未找到匹配的值,則返回值-1。

slice
slice 函數是與本機 JavaScript 切片函數等效的 observableArray(即,它將給定的起始索引中的數組條目返回到給定的結束索引)。 調用 myObservableArray.slice(...) 等效於在底層數組上調用相同的方法(即 myObservableArray().slice(...))。

操縱 observableArray
observableArray 公開了一組熟悉的函數,用於修改數組的內容並通知偵聽器。

pop, push, shift, unshift, reverse, sort, splice
所有這些函數等同於在底層數組上運行本機 JavaScript 數組函數,然後通知偵聽器有關更改:

  • push(value) — 將新項添加到數組的末尾。
  • pop() — 從數組中刪除最後一個值並返回它。
  • unshift(value) — 在數組的開頭插入一個新項。
  • shift() — 從數組中刪除第一個值並返回它。
  • reverse() — 反轉數組的順序並返回 observableArray(不是底層數組)。
  • sort() — 對數組內容進行排序並返回 observableArray。
    • 默認排序是按字母順序排列的,但您可以選擇傳遞一個函數來控制數組的排序方式。 你的函數應該接受數組中的任何兩個對象,如果第一個參數較小則返回負值,正值是第二個較小,或者為零以將它們視為相等。 例如,要按姓氏對“人”對像數組進行排序,您可以編寫 
    myObservableArray.sort(function (left, right) { 
        return left.lastName == right.lastName ? 0 : (left.lastName < right.lastName ? -1 : 1) 
    })
  • splice() — 從給定索引開始刪除並返回給定數量的元素。 例如,
    myObservableArray.splice(1, 3)
    從索引位置1(即第2,第3和第4個元素)開始刪除三個元素,並將它們作為數組返回。
有關這些observableArray函數的更多詳細信息,請參閱標準 JavaScript 數組函數的等效文檔

replace, remove and removeAll

observableArray 添加了一些默認情況下在JavaScript數組中找不到的更有用的方法:
  • replace( oldItem, newItem ) — 用 newItem 替換等於 oldItem 的第一個值。
  • remove( someItem ) — 刪除所有等於someItem的值,並將它們作為數組返回。
  • remove( function (item) { return item.age < 18; } ) — 刪除ageproperty小於18的所有值,並將它們作為數組返回。
  • removeAll( ['Chad', 132, undefined] ) — 刪除所有等於'Chad',123或undefined的值,並將它們作為數組返回。
  • removeAll() — 刪除所有值並將其作為數組返回。

destroy and destroyAll (Note: Usually relevant to Ruby on Rails developers only)

destroy和destroyAll函數主要是為了方便使用Ruby on Rails的開發人員:
  • destroy( someItem ) — Finds any objects in the array that equal someItem and gives them a special property called _destroy with value true.
  • destroy( function (someItem) { return someItem.age < 18; } ) — Finds any objects in the array whose age property is less than 18, and gives those objects a special property called _destroy with value true.
  • destroyAll( ['Chad', 132, undefined] ) — Finds any objects in the array that equal 'Chad'123, or undefined and gives them a special property called _destroy with value true.
  • destroyAll() — Gives a special property called _destroy with value true to all objects in the array.
那麼,這個_destroy的東西到底是什麼? 這對Rails開發人員來說真的很有趣。 Rails中的約定是,當您將動作傳遞給JSON對像圖時,框架可以自動將其轉換為ActiveRecord對像圖,然後將其保存到數據庫中。 它知道數據庫中已有哪些對象,並發出正確的INSERT或UPDATE語句。 要告訴框架刪除記錄,只需將_destroy設置為true即可。
請注意,當KO呈現 foreach 綁定時,它會自動將標記為 _destroyequal 的任何對象隱藏為true。 因此,您可以使用某種“刪除”按鈕來調用陣列上的 destroy(someItem)方法,這將立即導致指定的項目從可見的 UI 中消失。 稍後,當您將JSON對像圖提交給Rails時,該項也將從數據庫中刪除(而其他數組項將像往常一樣插入或更新)。

延遲和/或禁止更改通知

通常,observableArray會在更改後立即通知其訂閱者。 但是,如果observableArray重複更改或觸發昂貴的更新,您可以通過限製或延遲更改通知來獲得更好的性能。 這是使用rateLimit擴展器完成的,如下所示:
// Ensure it notifies about changes no more than once per 50-millisecond period
myViewModel.myObservableArray.extend({ rateLimit: 50 });



綁定 (Bindings)

控製文字和外觀
可見的綁定 - The visible binding
文本綁定The - text binding
html綁定The - html binding
css綁定The - css binding
樣式綁定The - style binding
attr綁定The - attr binding

控制流 - Control flow
foreach綁定 - The foreach binding
if綁定  - The if binding
ifnot綁定 - The ifnot binding
有約束力 - The with binding
組件綁定 - The component binding

使用表單域 - Working with form fields
點擊綁定 - The click binding
事件綁定 - The event binding
提交綁定 - The submit binding

提交綁定添加了一個事件處理程序,以便在提交關聯的 DOM 元素時調用所選的 JavaScript 函數。 通常,您只會在表單元素上使用它。

當您在表單上使用提交綁定時,Knockout 將阻止瀏覽器對該表單的默認提交操作。 換句話說,瀏覽器將調用您的處理程序函數,但不會將表單提交給服務器。 這是一個有用的默認值,因為當您使用提交綁定時,通常是因為您使用表單作為視圖模型的接口,而不是常規 HTML 表單。 如果您確實希望讓表單像普通的 HTML 表單一樣提交,只需從提交處理程序返回 true 即可。

Example
<form data-bind="submit: doSomething">
    ... form contents go here ...
    <button type="submit">Submit>/button>
</form>
 
<script type="text/javascript">
    var viewModel = {
        doSomething : function(formElement) {
            // ... now do something
        }
    };
</script>
如此示例所示,KO 將表單元素作為參數傳遞給提交處理函數。 如果需要,可以忽略該參數,或者有多種方法可以使用它,例如:

  • 從表單元素中提取其他數據或狀態
  • 使用類似於以下代碼段的代碼,使用 jQuery Validation 等庫觸發 UI 級驗證: 
    if ($(formElement).valid()) { /* do something */ }
    .

您可以引用任何JavaScript函數 - 它不必是視圖模型上的函數。 您可以通過編寫 submit:someObject.someFunction 來引用任何對像上的函數。

視圖模型上的函數稍微有點特殊,因為您可以按名稱引用它們,即,您可以編寫 submit:doSomething 而不必編寫 submit:viewModel.doSomething (雖然從技術上講也是有效的)。

啟用綁定 - The enable binding
禁用綁定 - The disable binding
價值綁定 - The value binding
textInput綁定 - The textInput binding
hasFocus綁定 - The hasFocus binding
檢查綁定 - The checked binding
選項綁定 - The options binding
selectedOptions綁定 - The selectedOptions binding
uniqueName綁定 - The uniqueName binding

渲染模板 - Rendering templates
模板綁定 - The template binding

綁定語法 - Binding syntax
數據綁定語法 - The data-bind syntax
綁定上下文 - The binding context

創建自定義綁定 - Creating custom bindings
創建自定義綁定 - Creating custom bindings
控制後代綁定 - Controlling descendant bindings
支持虛擬元素 - Supporting virtual elements
定制處理邏輯 - Custom disposal logic
預處理:擴展綁定語法 - Preprocessing: Extending the binding syntax

組件 - Components
概述:哪些組件和自定義元素提供 - Overview: What components and custom elements offer
定義和註冊組件 - Defining and registering components
組件綁定 - The component binding
使用自定義元素 - Using custom elements
高級:自定義組件加載器 - Advanced: Custom component loaders

更多技術 - Further techniques
加載和保存JSON數據 - Loading and saving JSON data
加載和保存JSON數據
Knockout允許您實現複雜的客戶端交互,但幾乎所有Web應用程序還需要與服務器交換數據,或者至少為本地存儲序列化數據。 交換或存儲數據最方便的方式是JSON格式 - 大多數Ajax應用程序目前使用的格式。

加載或保存數據
Knockout不會強制您使用任何特定技術來加載或保存數據。 您可以使用任何適合您所選服務器端技術的機制。 最常用的機制是jQuery的Ajax輔助方法,例如getJSON,post和ajax。 您可以從服務器獲取數據:

$.getJSON("/some/url", function(data) { 
    // Now use this data to update your view models, 
    // and Knockout will update your UI automatically 
})

var data = /* Your data in JSON format - see below */;
$.post("/some/url", data, function(returnedData) {
    // This callback is executed if the post was successful     
})

或者,如果您不想使用jQuery,則可以使用任何其他機制來加載或保存JSON數據。 所以,所有Knockout需要幫助你做的是:
  • 為了保存,請將您的視圖模型數據轉換為簡單的JSON格式,以便您可以使用上述技術之一發送它
  • 要加載,請使用您使用上述技術之一收到的數據更新視圖模型

將視圖模型數據轉換為Plain JSON
您的視圖模型是JavaScript對象,因此從某種意義上說,您可以使用任何標準JSON序列化程序(例如JSON.stringify(現代瀏覽器中的本機函數)或json2.js庫)將它們序列化為JSON。 但是,您的視圖模型可能包含可觀察對象,計算可觀察對象和可觀察數組,這些數組實現為JavaScript函數,因此不會在沒有代表您的額外工作的情況下乾淨地序列化。

為了便於序列化視圖模型數據,包括observable等,Knockout包含兩個輔助函數:

ko.toJS - 這會克隆你的視圖模型的對像圖,用每個observable替換該observable的當前值,這樣你就得到一個只包含你的數據而沒有Knockout相關工件的普通副本

ko.toJSON - 這會生成一個表示視圖模型數據的JSON字符串。 在內部,它只是在視圖模型上調用ko.toJS,然後在結果上使用瀏覽器的本機JSON序列化程序。 注意:為了在沒有本機JSON序列化程序(例如,IE 7或更早版本)的舊瀏覽器上工作,您還必須引用json2.js庫。

例如,定義視圖模型如下:

var viewModel = {
    firstName : ko.observable("Bert"),
    lastName : ko.observable("Smith"),
    pets : ko.observableArray(["Cat", "Dog", "Fish"]),
    type : "Customer"
};
viewModel.hasALotOfPets = ko.computed(function() {
    return this.pets().length > 2
}, viewModel)

它包含可觀察量,計算可觀察量,可觀察數組和普通值的混合。 您可以將其轉換為適合使用ko.toJSON發送到服務器的JSON字符串,如下所示:
var jsonData = ko.toJSON(viewModel);
 
// Result: jsonData is now a string equal to the following value
// '{"firstName":"Bert","lastName":"Smith","pets":["Cat","Dog","Fish"],"type":"Customer","hasALotOfPets":true}'

或者,如果您只想在序列化之前使用純JavaScript對像圖,請使用ko.toJS,如下所示:

var plainJs = ko.toJS(viewModel);
 
// Result: plainJS is now a plain JavaScript object in which nothing is observable. It's just data.
// The object is equivalent to the following:
//   {
//      firstName: "Bert",
//      lastName: "Smith",
//      pets: ["Cat","Dog","Fish"],
//      type: "Customer",
//      hasALotOfPets: true
//   }

請注意,ko.toJSON接受與JSON.stringify相同的參數。 例如,在調試Knockout應用程序時,對視圖模型數據進行“實時”表示會很有用。 要為此目的生成格式良好的顯示,可以將spaces參數傳遞給ko.toJSON並綁定到視圖模型,如:

<pre data-bind="text: ko.toJSON($root, null, 2)"</pre>

使用JSON更新視圖模型數據
如果您已從服務器加載了一些數據並希望使用它來更新視圖模型,那麼最直接的方法就是自己完成。 例如,

// Load and parse the JSON
var someJSON = /* Omitted: fetch it from the server however you want */;
var parsed = JSON.parse(someJSON);
 
// Update view model properties
viewModel.firstName(parsed.firstName);
viewModel.pets(parsed.pets);

在許多情況下,這種直接方法是最簡單和最靈活的解決方案。 當然,當您更新視圖模型上的屬性時,Knockout將負責更新可見的UI以匹配它。

但是,許多開發人員更喜歡使用更基於約定的方法來使用傳入數據更新其視圖模型,而無需為每個要更新的屬性手動編寫代碼行。 如果您的視圖模型具有許多屬性或深層嵌套的數據結構,這可能是有益的,因為它可以大大減少您需要編寫的手動映射代碼的數量。 有關此技術的更多詳細信息,請參閱knockout.mapping插件

擴展可觀察量 - Extending observables
延期更新 - Deferred updates
限速可觀察量 - Rate-limiting observables
不引人注意的事件處理 - Unobtrusive event handling
使用fn添加自定義函數 - Using fn to add custom functions
Microtasks - Microtasks
異步錯誤處理 - Asynchronous error handling

插件 - Plugins
映射插件The - mapping plugin

更多信息More - information
瀏覽器支持 - Browser support
獲得幫助 - Getting help
教程和示例的鏈接 - Links to tutorials & examples
AMD使用RequireJs(異步模塊定義)- Usage with AMD using RequireJs (Asynchronous Module Definition)
















參考來源: http://knockoutjs.com/documentation/observables.html