如果你想檢測并響應一個對象上的變化,你可以使用可觀察的對象。如果您想檢測和響應一系列對象的變化,請使用`observableArray`。這在許多場景中非常有用,在這些場景中,您正在顯示或編輯多個值,并且需要在添加和刪除項目時重復顯示和消失UI的各個部分。
示例:
```
var myObservableArray = ko.observableArray(); // Initially an empty array
myObservableArray.push('Some value'); // Adds the value and notifies observers
```
*****
關鍵點:ObservalArray跟蹤數組中的對象,而不是這些對象的狀態
簡單地將一個對象放入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添加了一些下面描述的附加功能)。因此,您可以通過將ObservalArray作為一個無參數的函數調用來獲取底層JavaScript數組,就像其他任何可觀察對象一樣。然后您可以從底層數組中讀取信息。例如:
```
alert('The length of the array is ' + myObservableArray().length);
alert('The first element is ' + myObservableArray()[0]);
```
從技術上講,您可以使用任何本機JavaScript數組函數來操作底層數組,但通常有更好的替代方法。KO的`observableArray`有自己的等效功能,它們更有用,因為:
它們適用于所有目標瀏覽器。(例如,本機JavaScript indexOf函數在ie8或更早版本上不起作用,但KO的indexOf可以在任何地方使用。)
對于修改數組內容的函數,如`push`和`splice`,KO的方法會自動觸發依賴項跟蹤機制,以便將更改通知所有注冊的偵聽器,并且您的UI會自動更新,這意味著使用KO的方法(即ObservalArray.push)之間存在顯著差異(…)和JavaScript本地數組方法(即`observeArray().push(…)`,因為后者不會向數組的訂閱者發送其內容已更改的任何通知。
*****
**indexOf**
indexOf函數返回與參數相等的第一個數組項的索引。例如,myObservableArray.indexOf('Blah')將返回第一個數組項的從零開始的索引,該索引等于Blah,如果找不到匹配值,則返回值-1。
*****
**slice**
slice 函數是原生 JavaScript 切片函數的 observableArray 等價物(即,它返回從給定開始索引到給定結束索引的數組條目)。 調用 myObservableArray.slice(...) 相當于在底層數組上調用相同的方法(即 myObservableArray().slice(...))。
*****
以下所有這些函數都相當于在底層數組上運行原生 JavaScript 數組函數,然后通知偵聽器有關更改:
push( value ) — 在數組末尾添加一個新項目。
pop() — 從數組中刪除最后一個值并返回它。
unshift( value ) — 在數組的開頭插入一個新項目。
shift() — 從數組中刪除第一個值并返回它。
reverse() — 反轉數組的順序并返回 observableArray(不是底層數組)。
sort() — 對數組內容進行排序并返回 observableArray。默認排序是按字母順序排列的,但您可以選擇傳遞一個函數來控制數組的排序方式。請參閱下面排序的示例。
splice() — 從給定索引開始移除并返回給定數量的元素。例如, myObservableArray.splice(1, 3) 從索引位置 1 開始刪除三個元素(即第 2、第 3 和第 4 個元素)并將它們作為數組返回。
*****
sorted和### reversed
`sorted()` — 返回數組的排序副本。 如果您想保留可觀察數組的原始順序但需要按特定順序顯示它,這比排序更可取。
默認排序是按字母順序排列的,但您可以選擇傳遞一個函數來控制數組的排序方式。 您的函數應該接受數組中的任意兩個對象,如果第一個參數較小,則返回負值,正值表示第二個較小,或者為零以將它們視為相等。 例如,要按姓氏對“person”對象數組進行排序,您可以編寫:
```
var mySortedArray = ko.pureComputed(function () {
return myObservableArray.sorted(function (left, right) {
return left.lastName === right.lastName ? 0
: left.lastName < right.lastName ? -1
: 1;
});
});
```
`reversed() `— 返回數組的反轉后的副本。
*****
replace,remove和removeAll
observableArray 添加了一些默認在 JavaScript 數組中找不到的更有用的方法:
replace( oldItem, newItem ) — 用 newItem 替換與 oldItem 相等的第一個值。
remove( someItem ) — 刪除所有等于 someItem 的值并將它們作為數組返回。
remove( function (item) { return item.age < 18; } ) — 刪除所有年齡屬性小于 18 的值,并將它們作為數組返回。
removeAll( ['Chad', 132, undefined] ) — 刪除所有等于 'Chad'、123 或 undefined 的值,并將它們作為數組返回。
removeAll() — 刪除所有值并將它們作為數組返回。
*****
確定屬性是否為 observableArray
在某些情況下,以編程方式確定您是否正在處理 observableArray 很有用。 Knockout 提供了一個實用函數 `ko.isObservableArray` 來幫助解決這種情況。
*****
通常,一個 observableArray 會在它發生更改后立即通知其訂閱者。 但是如果 observableArray 被重復更改或觸發昂貴的更新,您可能會通過限制或延遲更改通知來獲得更好的性能。 這是使用 rateLimit 擴展器完成的,如下所示:
```
// Ensure it notifies about changes no more than once per 50-millisecond period
myViewModel.myObservableArray.extend({ rateLimit: 50 });
```
跟蹤數組更改
盡管您可以像任何其他 observable 一樣訂閱和訪問 observableArray,但 Knockout 還提供了一種超快速方法來找出 observable 數組的變化情況(即,剛剛添加、刪除或移動了哪些項目)。 您訂閱數組更改如下:
```
obsArray.subscribe(fn, thisArg, "arrayChange");
```
訂閱變更的主要優點:
在大多數情況下,性能是 O(1),即基本上沒有性能影響,因為對于簡單的操作,(推送、拼接等)Knockout 提供更改日志而不運行任何差異算法。 如果您在不使用典型的數組變異函數的情況下進行了任意更改,則 Knockout 僅依賴于算法。
更改日志只為您提供實際更改的項目。
以下是如何報告更改的示例:
```
var myArray = ko.observableArray(["Alpha", "Beta", "Gamma"]);
myArray.push("Delta");
// Changes: [{ index: 3, status: 'added', value: 'Delta' }]
// New value: ["Alpha", "Beta", "Gamma", "Delta"]
myArray.pop();
// Changes: [{ index: 3, status: 'deleted', value: 'Delta' }]
// New value: ["Alpha", "Beta", "Gamma"]
myArray.splice(1, 2, "Omega");
// Changes:
// [{ index: 1, status: 'deleted', value: 'Beta' },
// { index: 1, status: 'added', value: 'Omega' },
// { index: 2, status: 'deleted', value: 'Gamma' }]
// New value: ["Alpha", "Omega"]
myArray.reverse();
// Changes:
// [{ index: 0, moved: 1, status: 'deleted', value: 'Alpha' },
// { index: 1, moved: 0, status: 'added', value: 'Alpha' }]
// New value: ["Omega", "Alpha"]
```
如上所示,更改報告為添加和刪除值的列表。 刪除項的索引引用原始數組,添加項的索引引用新數組。
當項目被重新排序時,如上面的最后一個例子所示,您還將獲得移動的信息。 您可以選擇忽略移動的信息,并將其解釋為刪除的原始 Alpha 和添加到數組末尾的不同 Alpha。 或者,您可以認識到移動的信息告訴您,您可以將添加和刪除的值視為僅更改位置的同一項目(通過匹配索引)。
observableArray 在構造時啟用了數組跟蹤,但您可以擴展任何其他訂閱(即 ko.observable 和 ko.computed),如下所示:
```
trackable = ko.observable().extend({trackArrayChanges: true});
```
- Magento概述
- 第一章:路線圖
- 概述
- 前端技能
- 后端技能
- 第二章:Linux環境
- 1.安裝虛擬機VirtualBox
- 2.創建虛擬機
- 3.安裝Ubuntu系統
- Linux文件系統概述
- Linux常用操作命令
- 第三章:Docker專題
- Docker概述
- 1.基礎
- 2.鏡像
- 3.容器
- 4.容器互聯
- 5.dockerfile
- 6.docker-compose
- 7.docker安裝nginx
- 8.docker安裝mysql
- 9.docker安裝redis
- 10.docker安裝php
- 11.docker配置nginx-php-mysql
- 12.docker-compose構建lamp
- 13.附錄
- 第四章:LAMP環境
- Docker構建LAMP開發環境
- 一鍵安裝LNMP/LAMP
- 第五章:Magento安裝
- Magento環境要求
- Docker安裝Magento
- 填充網站首頁、分類、商品等
- 第六章:Linux開發模式
- 編輯器vscode及插件
- 開發模式之SSH
- 開發模式之SFTP
- 開發模式之git
- 第七章:Magento架構
- 架構概述
- 文件目錄結構
- 數據庫表解析之EAV
- Magento命令行
- 第八章:模塊結構解析
- 模塊目錄結構
- 配置文件之env.php
- 配置文件-routes.xml
- 配置文件之module.xml
- 配置文件之webapi.xml
- 配置的方式及加載順序
- mvc之controller
- mvc之model
- mvc之block
- mvc之模板
- api概述
- 第九章:自定義模塊
- 自定義模塊概述
- 建立模塊
- 注冊模塊
- 創建控制器
- 創建Block
- 創建模板
- Model-Collection-ResourceModel
- 添加后臺菜單
- 第十章:重寫(Override)
- 重寫概述
- 布局文件詳解
- 定位布局文件
- 重寫Controller
- 重寫Template
- 重寫Block
- 重寫Model
- 重寫其它類
- 第十一章:小部件(Widget)
- 1.Widget概述
- 2.Widget在CMS頁面的應用
- 3.自定義一個Widget
- 4.Widget添加到前臺頁面
- 第十二章:主題(Theme)
- 主題概述
- 1.創建新的主題
- 2.添加全局css文件
- 3.模板分離到主題
- 4.主題模板與javascript
- 5.magento封裝的js寫法
- 6.layout布局解析
- 7.創建移動端主題
- 第十三章:Template專題
- 模板的指定
- 自定義模板
- 模板重寫的規則
- 第十四章:Javascript專題
- magento中的javascript
- requirejs語法
- js的調用和初始化
- js的重寫和擴展
- javascript使用mixins
- 第十五章:Knockoutjs專題
- knockoutjs的應用
- knockout簡介
- Observables
- Observable Arrays
- Computed Observables
- Bindings(綁定)
- Visible和hidden綁定
- Text綁定
- html綁定
- class和css綁定
- style綁定
- attr綁定
- 表單-click綁定
- 表單-submit綁定
- 表單-value值綁定
- 表單-textInput綁定
- 表單-checked綁定
- 表單-options綁定
- data-bind語法
- binding上下文
- 第十六章:Checkout專題
- 結算頁面概述
- 添加新的結帳步驟
- 添加自定義支付方式
- 結算前添加自定義驗證
- 添加自定義配送方式
- 添加自定義配送驗證
- 為郵政編碼添加掩碼
- 為字段添加自定義模板
- 結賬頁面添加新的input
- 在地址表單中添加字段
- 添加自定義配送地址
- 結算頁面其它字段修改
- 自定義運輸方式列表
- 線下支付方式添加字段
- 第十七章:實戰案例解析
- 從零開發一個模塊
- 1.需求分析
- 2.數據表與數據填充
- 3.建立module
- 4.路由
- 5.控制器
- 6.創建Block
- 7.創建布局
- 8.建立模板
- 9.建立Model層
- 10.查詢數據
- 11.完善模板
- 12.小結
- 定制我的訂單頁面
- 1.需求分析
- 2.新建模塊
- 3.重寫:布局文件
- 4.Block文件
- 5.模板文件
- 6.添加css文件
- 7.測試定制結果
- 添加系統配置模塊
- 1.需求分析
- 2.后臺實現
- 3.前臺實現
- 第三方登錄到magento
- 1.需求分析
- 2.登錄頁表單
- 3.建立module
- 4.建立控制器-后端登錄邏輯
- 5.建立控制器-登錄中間頁
- 6.建立中間頁的layout文件
- 7.建立block文件
- 8.建立登錄中間頁模板
- 9.第三方登錄擴展
- 保留心愿單商品
- 1.需求分析
- 2.Plugin機制-攔截器
- 3.心愿單修改示例
- 創建訂單流程及擴展
- 1.需求分析
- 2.創建訂單流程追蹤
- 3.重寫
- 用戶注冊添加字段
- 1-需求分析
- 2-功能實現
- 第十八章:RestApi專題
- webapi概述
- 如何訪問一個api
- swagger介紹
- 將services配置為webapi
- 配置api示例
- 設置自定義路由
- 第十九章:設計模式專題
- 設計模式概述
- 創建型模式
- 工廠方法
- 抽象工廠
- 生成器
- 原型
- 單例
- 結構型模式
- 適配器
- 橋接
- 組合
- 裝飾
- 外觀
- 享元
- 代理
- 行為模式
- 責任鏈
- 命令
- 迭代器
- 中介者
- 備忘錄
- 觀察者
- 狀態
- 策略
- 模板方法
- 訪問者
- 第二十章:性能最佳實踐
- 本章概述
- 硬件推薦
- 軟件推薦
- 架構參考
- 開發環境建議
- 配置最佳實踐
- 部署流程
- 高級設置
- 附錄1:常用代碼及問題整理
- 權限報錯問題
- Magento定時任務
- Magento開發基礎篇一
- Magento開發基礎篇二
- Magento之CRUD
- Magento中獲取各種url的方法
- Redis存儲Session和緩存
- 發送郵件配置
- 檢測用戶登錄信息
- 獲取env.php中配置的變量
- 模板中獲取當前頁面url
- 獲取用戶默認配送地址
- Magento系統問題整理
- 結算頁面不能選擇賬單地址
- 我應該執行什么命令?
- 追代碼打印sql
- 忘記后臺密碼怎么辦?
- 附錄2:多語言應用
- 多語言概述
- 日語翻譯引擎
- 附錄3:插件安裝與GMO
- 安裝插件的方法
- GMO支付插件
- 附錄4:Elasticsearch搜索和分詞
- ElasticSearcch配置與安裝
- ES實現搜索日語分詞