Knockout旨在允许您将任意JavaScript对象用作视图模型。 只要一些视图模型的属性是observables,您可以使用KO将它们绑定到您的UI,并且UI将在可观察属性更改时自动更新。

大多数应用程序需要从后端服务器获取数据。 由于服务器没有任何可观察的概念,它只提供一个纯JavaScript对象(通常序列化为JSON)。 映射插件提供了一种简单的方法来将该简单的JavaScript对象映射到具有适当的observables的视图模型中。 这是替代手动编写自己的JavaScript代码,根据您从服务器获取的一些数据构建视图模型。

下载映射插件(你需要翻个墙)

示例:不带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结构)到可观察视图模型的映射。

示例:使用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/

再次感谢

KnockoutJS 3.X API 第八章 映射(mapping)插件的更多相关文章

  1. elasticsearch的映射(mapping)和分析(analysis)

    转发自:http://blog.csdn.net/hzrandd/article/details/47128895 分析和分析器 分析(analysis)是这样一个过程: 首先,表征化一个文本块为适用 ...

  2. ES 11 - 配置Elasticsearch的映射 (mapping)

    目录 1 映射的相关概念 1.1 什么是映射 1.2 映射的组成 1.3 元字段 1.4 字段的类型 2 如何配置mapping 2.1 创建mapping 2.2 更新mapping 2.3 查看m ...

  3. KnockoutJS 3.X API 第七章 其他技术(1) 加载和保存JSON数据

    Knockout允许您实现复杂的客户端交互性,但几乎所有Web应用程序还需要与服务器交换数据,或至少将本地存储的数据序列化. 最方便的交换或存储数据的方式是JSON格式 - 大多数Ajax应用程序今天 ...

  4. knockoutJS学习笔记09:使用mapping插件

    一.问题引出 通常,我们先定义好html结构或者模板,通过ajax向后台发起请求,后台返回json数据,然后再将json数据渲染到页面上.以博客园个人博客里的个人信息为例子,如图: 1.定义html. ...

  5. Elasticsearch 通关教程(二): 索引映射Mapping问题

    数据库建表的时候,我们的DDL语句一般都会指定每个字段的存储类型,例如:varchar,int,datetime等等,目的很明确,就是更精确的存储数据,防止数据类型格式混乱. CREATE TABLE ...

  6. 【转】Python数据类型之“集合(Sets)与映射(Mapping)”

    [转]Python数据类型之“集合(Sets)与映射(Mapping)” 一.集合类型(Sets) 集合对象是不同的(不可重复)hashable对象的无序集合.常见用法包括:成员关系测试.移除序列中的 ...

  7. 10.2.翻译系列:使用Fluent API进行属性映射【EF 6 Code-First】

    原文链接:https://www.entityframeworktutorial.net/code-first/configure-property-mappings-using-fluent-api ...

  8. MVVM架构~knockoutjs系列之Mapping插件为对象添加ko属性

    返回目录 对于一个JS对象来说,如果希望将所有属性进行监视,在之前我们需要一个个对属性添加ko.observable方法,而有了Mapping插件后,它可以帮助我们这件事. 在Mapping出现之前 ...

  9. 7.Knockout.Js(Mapping插件)

    前言 Knockout设计成允许你使用任何JavaScript对象作为view model.必须view model的一些属性是observable的,你可以使用KO绑定他们到你的UI元素上,当这些o ...

随机推荐

  1. 【刷题笔记】火车购票-----java方案

    问题描述请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配. 假设一节车厢有20排.每一排5个座位.为方便起见,我们用1到100来给所有的座位编号,第一排是1到5号,第二排是6到10号 ...

  2. Scrum 项目4.0

    队友: 郭志豪:http://www.cnblogs.com/gzh13692021053/ 杨子健:http://www.cnblogs.com/yzj666/ 刘森松:http://www.cnb ...

  3. iOS 使点击事件穿透透明的UIView

    如图: 悬浮的三个按钮下方有一个可以点击的灰色区域,但是点击按钮之间的透明区域, 这三个按钮的contentView会响应这个点击事件,这时候需要让这个contentView不响应这个点击事件. 解决 ...

  4. QuartZ Cron表达式

     Cron Expressions cron的表达式是字符串,实际上是由七子表达式,描述个别细节的时间表.        Seconds        Minutes        Hours     ...

  5. Linux 学习记录

    整理学习Linux操作系统遇到的不理解的概念.逐个进行补充.我们用的版本是CentOs. what's the gcc? what's the yum? what's the wget?

  6. Hibernate中Criteria的完整用法

    1,CriteriaHibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口,下面提供了 Criteria和DetachedCriteria .2,De ...

  7. 浅谈MySql的存储引擎(表类型)

    来源:http://www.cnblogs.com/lina1006/archive/2011/04/29/2032894.html 什么是MySql数据库 通常意义上,数据库也就是数据的集合,具体到 ...

  8. Redis 做消息队列

    一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式.利用redis这两种场景的消息队列都能够实现.定义: 生产者消费者模式:生产者生产消息放到队列里,多个消费者同时监听队列, ...

  9. 关于click和submit的笔记

    click主要用于元素的点击时的响应事件,而submit是指表单元素form的提交事件. 但是,当click加入到表单的提交按钮时,事情似乎就有点复杂,总是忘记了.这两天搜了下,又实践了一下. 主要用 ...

  10. mysql多字段排序

    在对数据库进行查询的时候有时候需要将查询的结果按照某字段升序或者降序排列,甚至有时候需要按照某两个字段进行升降序排列.如果按照某一字段进行排列,只需要在查询语句最后写上 "order by ...