KnockoutJS 3.X API 第八章 映射(mapping)插件

来源:http://www.cnblogs.com/smallprogram/archive/2016/10/19/5976866.html
-Advertisement-
Play Games

Knockout旨在允許您將任意JavaScript對象用作視圖模型。 只要一些視圖模型的屬性是observables,您可以使用KO將它們綁定到您的UI,並且UI將在可觀察屬性更改時自動更新。 大多數應用程式需要從後端伺服器獲取數據。 由於伺服器沒有任何可觀察的概念,它只提供一個純JavaScri... ...


Knockout旨在允許您將任意JavaScript對象用作視圖模型。 只要一些視圖模型的屬性是observables,您可以使用KO將它們綁定到您的UI,並且UI將在可觀察屬性更改時自動更新。

大多數應用程式需要從後端伺服器獲取數據。 由於伺服器沒有任何可觀察的概念,它只提供一個純JavaScript對象(通常序列化為JSON)。 映射插件提供了一種簡單的方法來將該簡單的JavaScript對象映射到具有適當的observables的視圖模型中。 這是替代手動編寫自己的JavaScript代碼,根據您從伺服器獲取的一些數據構建視圖模型。

下載映射插件(你需要翻個牆)

<br class="Apple-interchange-newline"><div id="inner-editor"></div>

示例:不帶ko.mapping插件的手動映射

您要顯示當前伺服器時間和您的網頁上的用戶數。 您可以使用以下視圖模型表示此信息:

var viewModel = {
    serverTime: ko.observable(),
    numUsers: ko.observable()
}

您可以將此視圖模型綁定到一些HTML元素,如下所示:

The time on the server is: <span data-bind='text: serverTime'></span>
and <span data-bind='text: numUsers'></span> user(s) are connected.

由於視圖模型屬性是可觀察的,KO將在這些屬性更改時自動更新HTML元素。

接下來,您要從伺服器獲取最新數據。 每5秒您可以發出一個Ajax請求(例如,使用jQuery的$ .getJSON或$ .ajax函數):

var data = getDataUsingAjax();          // Gets the data from the server

伺服器可能返回類似於以下內容的JSON數據:

{
    serverTime: '2010-01-07',
    numUsers: 3
}

最後,要使用此數據更新視圖模型(不使用映射插件),您應該寫:

// Every time data is received from the server:
viewModel.serverTime(data.serverTime);
viewModel.numUsers(data.numUsers);

你必須為你想在頁面上顯示的每個變數這樣做。 如果您的數據結構變得更加複雜(例如,它們包含子節點或包含數組),則手動處理變得非常麻煩。 映射插件允許您做的是創建從常規JavaScript對象(或JSON結構)到可觀察視圖模型的映射。

<br class="Apple-interchange-newline"><div id="inner-editor"></div>

示例:使用ko.mapping

要通過映射插件創建視圖模型,請將上面代碼中的viewModel的創建替換為ko.mapping.fromJS函數:

// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);

如何映射

  • 對象的所有屬性都將轉換為observable。 如果更新將更改值,它將更新observable。
  • 數組被轉換為可觀察數組。 如果更新會更改項目數,則它將執行適當的添加/刪除操作。 它還將嘗試保持與原始JavaScript數組相同的順序。

取消映射

如果要將映射對象轉換回常規JS對象,請使用:

var unmapped = ko.mapping.toJS(viewModel);

這將創建一個未映射的對象,只包含作為原始JS對象的一部分的映射對象的屬性。 因此,換句話說,您手動添加到視圖模型的任何屬性或函數都將被忽略。 預設情況下,此規則的唯一例外是_destroy屬性,它也將被映射回來,因為它是Knockout在從ko.observableArray中銷毀項目時可能生成的屬性。 有關如何配置此項的更多詳細信息,請參閱“高級應用”章節。

使用JSON字元串

如果您的Ajax調用返回一個JSON字元串(並且不將其反序列化為JavaScript對象),那麼您可以使用函數ko.mapping.fromJSON來創建和更新視圖模型。 要取消映射,可以使用ko.mapping.toJSON。

除了它們使用JSON字元串而不是JS對象的事實,這些函數與它們的JS對象完全相同。

高級用法

有時,可能有必要對如何執行映射有更多的控制。 這是使用映射選項實現的。 它們可以在ko.mapping.fromJS調用期間指定。 在後續調用中,您不需要再次指定它們。

在這種情況下,您可能需要使用這些映射選項。

使用“key”唯一標識對象

假設您有一個類似於以下內容的JavaScript對象:

var data = {
    name: 'Scot',
    children: [
        { id : 1, name : 'Alicw' }
    ]
}

您可以將此映射到視圖模型沒有任何問題:

var viewModel = ko.mapping.fromJS(data);

現在,假設數據更新為沒有任何拼寫錯誤:

var data = {
    name: 'Scott',
    children: [
        { id : 1, name : 'Alice' }
    ]
}

這裡發生了兩件事情:name從Scot改為Scott,children[0] .name從Alicw變成了Alice。 您可以基於此新數據更新viewModel:

ko.mapping.fromJS(data, viewModel);

和名稱會改變,如預期。 但是,在children數組中,子(Alicw)將被完全刪除,並添加一個新的(Alice)。 這不是完全你會期望的。 相反,你會希望只有孩子的name屬性從Alicw更新到Alice,而不是整個孩子被替換!

這是因為,預設情況下,映射插件只是比較數組中的兩個對象。 因為在JavaScript中,對象{id:1,name:'Alicw'}不等於{id:1,name:'Alice'},它認為整個孩子需要被刪除並被一個新的替換。

要解決這個問題,你可以指定映射插件應該使用哪個鍵來確定對象是新的還是舊的。 你可以這樣設置:

var mapping = {
    'children': {
        key: function(data) {
            return ko.utils.unwrapObservable(data.id);
        }
    }
}
var viewModel = ko.mapping.fromJS(data, mapping);

這樣,每次映射插件檢查children數組中的一個項目時,它只會查看id屬性來確定一個對象是否被完全替換或只是需要更新。

使用“create”定製對象構造

如果你想自己處理映射的一部分,你也可以提供一個create回調。 如果這個回調存在,映射插件將允許你自己做這部分的映射。

假設您有一個類似於以下內容的JavaScript對象:

var data = {
    name: 'Graham',
    children: [
        { id : 1, name : 'Lisa' }
    ]
}

如果你想自己映射children數組,你可以這樣指定:

var mapping = {
    'children': {
        create: function(options) {
            return new myChildModel(options.data);
        }
    }
}
var viewModel = ko.mapping.fromJS(data, mapping);

提供給create回調的options參數是一個JavaScript對象,其中包含:

  • data: 包含此子項的數據的JavaScript對象
  • parent: 此子項所屬的父對象或數組

當然,在創建回調中你可以做另一個調用ko.mapping.fromJS如果你願意。 一個典型的用例可能是,如果你想用一些額外的計算observables擴充原始的JavaScript對象:

var myChildModel = function(data) {
    ko.mapping.fromJS(data, {}, this);
     
    this.nameLength = ko.computed(function() {
        return this.name().length;
    }, this);
}

使用“update”定製對象更新

您還可以通過指定更新回調來自定義對象的更新方式。 它將接收它試圖更新的對象和一個與create回調所使用的相同的選項對象。 您應該返回更新的值。

提供給更新回調的options參數是一個JavaScript對象,包含:* data:包含此子節點數據的JavaScript對象* parent:此子節點所屬的父對象或數組* observable:如果屬性是可觀察的 將被設置為實際可觀察的

下麵是一個配置示例,將在更新之前向輸入數據添加一些文本:

var data = {
    name: 'Graham',
}
 
var mapping = {
    'name': {
        update: function(options) {
            return options.data + 'foo!';
        }
    }
}
var viewModel = ko.mapping.fromJS(data, mapping);
alert(viewModel.name());

這將彈窗提示Graham Foo!

使用“ignore”忽略某些屬性

如果你想映射插件忽略你的JS對象的一些屬性(即不映射它們),你可以指定一個屬性名稱數組來忽略:

var mapping = {
    'ignore': ["propertyToIgnore", "alsoIgnoreThis"]
}
var viewModel = ko.mapping.fromJS(data, mapping);

您在映射選項中指定的忽略數組與預設忽略數組相結合。 你可以像這樣操作這個預設數組:

var oldOptions = ko.mapping.defaultOptions().ignore;
ko.mapping.defaultOptions().ignore = ["alwaysIgnoreThis"];

使用“include”包括某些屬性

當將視圖模型轉換回JS對象時,預設情況下,映射插件將僅包含屬於原始視圖模型的屬性,但它也將包括Knockout生成的_destroy屬性,即使它不是原始對象的一部分 。 但是,您可以選擇自定義此數組:

var mapping = {
    'include': ["propertyToInclude", "alsoIncludeThis"]
}
var viewModel = ko.mapping.fromJS(data, mapping);

您在映射選項中指定的include數組與預設的include數組相結合,預設情況下只包含_destroy。 你可以像這樣操作這個預設數組:

var oldOptions = ko.mapping.defaultOptions().include;
ko.mapping.defaultOptions().include = ["alwaysIncludeThis"];

使用“copy”複製某些屬性

將視圖模型轉換回JS對象時,預設情況下,映射插件將根據上述規則創建可觀察項。 如果你想強制映射插件簡單地複製屬性而不是使其可見,添加其名稱到“複製”數組:

var mapping = {
    'copy': ["propertyToCopy"]
}
var viewModel = ko.mapping.fromJS(data, mapping);

您在映射選項中指定的副本數組與預設副本數組相結合,預設情況下為空。 你可以像這樣操作這個預設數組:

var oldOptions = ko.mapping.defaultOptions().copy;
ko.mapping.defaultOptions().copy = ["alwaysCopyThis"];

僅使用“observe”觀察某些屬性

如果你希望映射插件只創建你的JS對象的一些屬性的可觀察和複製,你可以指定一個屬性名稱數組觀察:

var mapping = {
    'observe': ["propertyToObserve"]
}
var viewModel = ko.mapping.fromJS(data, mapping);

您在映射選項中指定的觀察數組與預設的觀察數組相結合,預設情況下為空。 你可以像這樣操作這個預設數組:

var oldOptions = ko.mapping.defaultOptions().observe;
ko.mapping.defaultOptions().observe = ["onlyObserveThis"];

數組忽略並包括仍然正常工作。 數組副本可用於複製數組或對象屬性(包括子元素)的效率。 如果在copy或observe中沒有指定數組或對象屬性,那麼它將被遞歸映射:

var data = {
    a: "a",
    b: [{ b1: "v1" }, { b2: "v2" }] 
};
 
var result = ko.mapping.fromJS(data, { observe: "a" });
var result2 = ko.mapping.fromJS(data, { observe: "a", copy: "b" }); //will be faster to map.

結果和結果2將是:

{
    a: observable("a"),
    b: [{ b1: "v1" }, { b2: "v2" }] 
}

複製和觀察可以衝突:

var data = {
    a: "a",
    b: [{ b1: "v1" }, { b2: "v2" }] 
};
var result = ko.mapping.fromJS(data, { observe: "b[0].b1"});
var result2 = ko.mapping.fromJS(data, { observe: "b[0].b1", copy: "b" });

結果將是:

{
    a: "a",
    b: [{ b1: observable("v1") }, { b2: "v2" }] 
}

結果2將是:

{
    a: "a",
    b: [{ b1: "v1" }, { b2: "v2" }] 
}

指定更新目標

如果,像在上面的例子中,你正在一個類中執行映射,你希望有它作為你的映射操作的目標。 ko.mapping.fromJS的第三個參數指示目標。 例如,

ko.mapping.fromJS(data, {}, someObject); // overwrites properties on someObject

所以,如果你想映射一個JavaScript對象到這裡,你可以傳遞這個作為第三個參數:

ko.mapping.fromJS(data, {}, this);

從多個來源映射

您可以通過應用多個ko.mapping.fromJS調用在一個視圖模型中組合多個JS對象,例如:

var viewModel = ko.mapping.fromJS(alice, aliceMappingOptions);
ko.mapping.fromJS(bob, bobMappingOptions, viewModel);

在每個調用中指定的映射選項將被合併。

映射監控屬性數組

由映射插件生成的可觀察數組通過一些可以利用鍵映射的函數來擴充:

  • mappedRemove
  • mappedRemoveAll
  • mappedDestroy
  • mappedDestroyAll
  • mappedIndexOf

它們在功能上等同於常規的ko.observableArray函數,但是可以基於對象的鍵來做事情。 例如:

var obj = [
    { id : 1 },
    { id : 2 }
]
 
var result = ko.mapping.fromJS(obj, {
    key: function(item) {
        return ko.utils.unwrapObservable(item.id);
    }
});
 
result.mappedRemove({ id : 2 });

映射的observablearray還公開了一個映射的Create函數:

var newItem = result.mappedCreate({ id : 3 });

它將首先檢查鍵是否已經存在,如果是,將拋出異常。 接下來,它將調用create和update回調(如果有的話)來創建新對象。 最後,它將把這個對象添加到數組並返回它。

KnockoutJS 3.X 結語

至此,所有KnockoutJS 3.X的API文檔撰寫完畢,希望這個完整的KnockoutJS中文文檔能對你有所幫助,感謝你的閱讀。如果你覺得不錯,請點一波推薦,關註。如果你覺得文中有那些不妥,歡迎批評指正。

感謝您的閱讀。

轉載請註明出處:http://www.cnblogs.com/smallprogram/ 

再次感謝


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.領域驅動簡介 領域驅動本身是一款古老的軟體建模思想 領域驅動兩大特性:通用語言.限界上下文 1.通用語言是一種思想.解釋是:團隊共用的術語.便於交流.//比如行業的術語或者.一個圈子內通俗的名稱如開發者們對Visual Studio 的簡稱:VS. 2.限界上下文是整個應用程式之內一種概念性邊界 ...
  • 回到目錄 對於Lind.DDD這個敏捷框架來說,插件也是其中的一個亮點,所有被認為是插件(Plugins)的模塊都會繼承自IPlugins這個標示介面,它在程式啟動時會找到所有插件,並通過autofac註冊到運行時中,然後在使用時通過PluginManager對象進行獲取,即所有模塊只註冊一次,在使 ...
  • 談談互聯網後端基礎設施 談談互聯網後端基礎設施 來自:http://chuansong.me/n/717637351233 對於一個互聯網企業,後端服務是必不可少的一個組成部分。拋開業務應用來說,往下的基礎服務設施做到哪些才能夠保證業務的穩定可靠、易維護、高可用呢?縱觀整個互聯網技術體系再結合公司的 ...
  • 文檔目錄 本節內容: 簡介 一個快速示例 其它特性 啟動模板 如何使用 簡介 我們總是對不同的需求開發不同的應用。但至少在某些層面上,一次又一次地重覆實現通用的和類似的功能。如:授權,驗證,異常處理,日誌,本地化,資料庫連接管理,設置管理,審核日誌等功能。所以我們創建架構和最佳實踐,如分層和模塊架構 ...
  • letter-spacing:3px的意思就是字母之間的間距是3px; ...
  • × 目錄 [1]原理介紹 [2]代碼實現 [3]實例應用 前面的話 在運動系列中,前面分別介紹了勻速運動、變速運動和曲線運動。下麵介紹一種特殊的運動形式——抖動 原理介紹 抖動其實是往複運動的一種特殊形式,只不過往複運動是一種無摩擦力的無限運動,且以速度為參照依據;而抖動以位置作為參照依據,最終停在 ...
  • Waud.js 是一個Web音頻庫,有一個HTML5音頻降級處理方案。 它允許您利用Web音頻API為你的Web應用程式控制音頻功能。在不支持Web音頻API的非現代瀏覽器使用HTML5音頻降級方案。 ...
  • 關於本系列文章 本系列文章總共8個章節,41篇文章,主要翻譯自官方API文檔,加上自己的一些理解撰寫而成。 區別與園子和網路上的其他一些Knockout教程,這個系列教程將由淺入深的系統的介紹Knockout的知識點和使用細節。 並且本系列KnockoutJS教程是基於最新的3.4.0版本入手的。對... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...