最近马上要开始一个新项目的研发,作为第一次mvvm应用的尝试,我决定使用knockoutjs框架。作为学习的开始就从官网的Document翻译开始吧,这样会增加印象并加入自己的思考,说是翻译也并不是纯粹的翻译,会加入自己对知识点的思考以及自己的尝试,在系列最后也希望用一个应用案例作为结尾。希望自己能坚持下来并有所收获,理解不对的地方大家也指出来避免我”误入歧途“。也并不会翻译所有的内容,我会根据自己的经验选择最能反映它使用和精髓的部分。当前版本为3.4

好了,闲言少叙,正篇开始。

  

  ===================================华丽的分割线============================================

knocket主要围绕由以下三个核心特征组成:

  1. Observables(观察器)与dependency tracking(依赖追踪)
  2. Declarative bindings(声明式绑定)
  3. Templating(模板)

MVVM and View Models

Model-View-View Model (MVVM) 是一种创建用户界面或用户接口的设计模式。你可以通过将UI拆分成下面三个部分从而将复杂的UI简洁化,清晰化:

  • Model(数据模型): 应用程序存储数据。模型包括了你应用程序域中与业务相关的数据以及这些数据对应的操作(例如 一个银行账户模型具有转账的功能)并且它跟UI是相互独立 的。 当时用KO的时候,通常这类模型是通过ajax从服务器端进行获取的。
  • ViewModel(视图模型): 服务于数据模型,为数据模型在UI上的展现及UI上的操作进行包装服务。 例如, 如果你要在UI上做一个列表展现, 你的视图模型将会是包含一个数据集合的对象, 并提供一些添加和删除数据的相关方法。需要注意的是视图模型并不是UI本身,它并不包括任何UI元素,比如按钮啊,标签啊样式之类。它也不是持久化的数据对象,它只是为数据模型临时保存一些用户正在处理的数据。当我们在使用KO的时候,它无非就是一些纯粹的javascript对象而已。
  • view(视图): 一个可视,可交互的真正的UI展现,他展现着视图模型的当前状态。它所展现的信息来自于视图模型,并且向视图模型发送命令执行动作 (例如: 当用户点击按钮的时候,视图向视图模型发送命令,视图模型进行真正的操作),并且当视图模型属性发生变化的时候,视图会自动进行展现的更新。当时用KO的时候,你的视图中的Html元素内容可以通过声明式绑定与视图模型进行连接从而决定UI如何展现。另外,你也可以通过使用模板的方式来使用视图模型中的数据生成UI中的Html内容。(模板后面会提到)

好了,让我们来举个很小的例子来看看上面说的视图与视图模型在KO中是如何协作的。创建一个视图模型对象非常容易,随意声明一个javascript对象我们就可以将它作为视图模型对象。例如:

 //创建一个视图模型对象 var myViewModel = {personName: 'Bob',personAge: 123}; ko.applyBindings(myViewModel);//ko是knockoutjs中的全局对象,这句话的意思是将数据模型对象与UI中所有有data-bind的属性进行声明绑定的元素进行连接

然后我们就可以创建一个非常简单的视图来展现上面的视图对象。还记得吗?他们使用声明式绑定来进行连接。下面的视图用来展现视图模型对象中的personName数据。

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

好了现在如果运行页面的话将会显示如下运行结果:

通过上面的例子我们可以看到,在UI上赋值我们并没有像jquery一样通过js来控制,而是使用声明绑定的方式在UI元素和js数据对象上建立联系,自动展现。在上面的代码标签中data-bind 并不是Html中的原生标记,它在Html5中得到浏览器的支持,是KO框架用来进行声明式绑定的工具,所以在KO中进行声明式绑定,都通过data-bind属性进行。有了视图模型,有了相应视图,最后要进行两者的连接了,所以下面这行代码必不可少:

ko.applyBindings(myViewModel); //将myViewModel对象与UI中所有进行了声明式绑定的元素进行连接,注意:是所有。

完整测试代码:

The name is <span data-bind="text: personName"></span>
@section scripts
{<script src="~/Scripts/knockout-3.4.0.js"></script><script type="text/javascript">$(function () {var myViewModel = {personName: 'Bob',personAge: 123};ko.applyBindings(myViewModel);});</script>
}

关于ko.appyBindings(myViewModel)中参数的作用说明一下:第一个参数说明在整个UI中你希望使用哪个视图模型对象与视图中的声明绑定进行连接。你也可以传递第二个参数来决定这个视图模型与UI中的哪个特定的声明式绑定(data-bind)进行连接,而不是与所有的进行连接。举个例子, ko.applyBindings(myViewModel, document.getElementById('someElementId'))。这就限制了这个视图模型对象只能与ID为someElementId 的Html元素对象以及它的后代元素对象进行连接,这样的话当你想要定义多个视图模型对象并且与页面中不同的元素进行绑定的时候就会特别有用。到目前为止真的是相当简单吧。

   Observables

好了,你已经看到了如何创建一个基本的视图模型以及如何通过绑定进行它的属性数据的展现。但是使用KO一个核心的好处是当视图模型内容改变的时候它还会自动更新你的UI,反之亦然。这有时会大大简化你的代码(我们稍后展示这个效果)。那么KO如何知道你的视图模型什么时候发生了改变进而更新你的UI呢?答案是:你需要将你的数图模型中的属性声明为observable类型对象。 observables类型对象非常特殊,当视图模型发生改变的时候,他们可以向订阅者发出通知,并自动建立与订阅者的关系,订阅者也就是具有声明式绑定的元素。举个例子, 重写一下上面的代码如下:

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

现在,你完全不需要视图 data-bind 声明部分保持不变. 与之前代码不同的是,现在ko可以自动监测变化了, 一旦视图模型有数据发生变化,它就会自动更新视图。

Observables属性的读取与写入

     要读取observable的当前值,只需要像调用方法一样以无参数的方式调用它。以上面的代码为例, myViewModel.personName() 将会返回 'Bob',而myViewModel.personAge() 将返回123。

要向observable属性中写入一个值的话也跟上面一样进行调用,只不过传入一个你想要写入的新值就可以了。举个例子:调用myViewModel.personName('Mary') 将会为personName赋一个新的名字。另外KO还提供了一个非常方便的代码链写法。 像这样:myViewModel.personName('Mary').personAge(50) 会修改personName为 'Mary' ,personAge修改为 50。

observables的核心作用就是"观察" ,也就是说, 被声明为observable的属性将来是会被双向通知的,它通知其它UI元素它已经被修改了,并且观察相关UI元素内容,并将变化值更新到ViewModel对象上。KO框架中的很多内置绑定就是用来干这事儿的。所以,当你在UI元素上(例如span标签)写上data-bind="text: personName"的时候 text 绑定类型将把这个span元素进行注册并做好被通知的准备只要视图对象上的personName发生了该表,span就会被通知修改内部的文本内容(假设personName是一个observable值,另外除了text绑定还有许多其它类型绑定,我们后面提到)。

当你通过调用myViewModel.personName('Mary')来修改personName的值的时候, text绑定将会自动更新相关DOM元素的text内容 。

observables的显示订阅处理

    通常你无需干预订阅的过程,所以初学者可以暂时跳过这一小节。

当observable类型数据发生改变后如果你希望在这个过程中做一些处理,你可以调用observable属性上的subscribe方法来将自己的处理代码注册进来。举个例子:

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

上面这段代码执行后,如果修改了personName的值后,那么将会弹出一个警告框,并且通过newValue参数可以获取当前正在更新的值。这个过程叫订阅注册。

subscribe方法接受三个传入参数callback 是一个function当通知到来时会自动执行, target (可选) 定义了在callback方法中 this代表了哪个对象(默认的话this就是当前视图模型对象), event(可选; 默认值是"change") 事件名称,是指当什么类型的事件发生的时候会有通知到来,默认情况下就是当值发生改变的时候。(其它类型我们后面谈到)。

当然了,一旦你注册了一个自己的订阅,你也可以根据需要在未来的某个时候取消这个订阅,你需要先定义一个变量来接收subscribe当前的返回值,然后调用dispose方法。代码如下

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

如果你希望在observable类型值在发生改变,但被赋值之前做一些处理的话,你也可以在beforeChange 事件上注册自己的处理,代码如下:

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

注意: Knockout 是否触发上面的订阅还有一个默认条件就是新的值必须与老的值不相同,如果赋值时是相同值的话那么将不会触发这两个订阅。如果需要更改这种默认动作可以使用订阅器上的extend方法来修改。代码如下:

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

最后,如果你的observable属性在更新时的动作比较耗时或者会更新的很频繁,你可以通过限制通知的时间间隔,毕竟订阅通知会有性能影响。做法如下:

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

这样的话就算是频繁更新属性值,每次通知的事件间隔也会控制在50毫秒。测试代码如下:

<button type="button" id="btnStart">点击测试</button>
<span id="clickcontent"></span>
@section scripts {<script src="~/Scripts/knockout-3.4.0.js"></script><script type="text/javascript">$(function () {var myViewModel = {//personName: ko.observable("ZhouBo")
                personName: ko.observable("ZhouBo")};myViewModel.personName.extend({ notify: 'always' });myViewModel.personName.extend({ rateLimit: 5000 });ko.applyBindings(myViewModel);var index = 0;$('#btnStart').click(function () {$('#clickcontent').text(++index);myViewModel.personName(++index);});});

说明:如果我快速点击按钮 btnStart,则5秒钟之后第一个span的内容才会发生变化,也就是5庙后才发送了一次通知。

转载于:https://www.cnblogs.com/MichaelBang/p/5589421.html

Knockoutjs官网翻译系列(一)相关推荐

  1. Knockoutjs官网翻译系列(二) Observable 数组

    承接前文,前文书说道了KO框架中如何使用observable的视图模型属性来与UI元素进行绑定并自动进行双向更新的事儿.observable属性除了服务基础数据类型之外,还定义了专门为服务数组类型的o ...

  2. git lfs官网翻译

    git lfs官网翻译 下载地址:https://git-lfs.github.com/ git lfs说明: Git Large File Storage(LFS) 将大型文件(如音频示例.视频.数 ...

  3. CoherenceModel官网翻译

    CoherenceModel官网翻译 models.coherencemodel – Topic coherence pipeline 计算主题模型的主题一致性.这是论文四个阶段主题一致性管道的实现. ...

  4. Hyperledger Fabric 官网翻译入门教程--之关键概念(Hyperledger Fabric 模型)

    英文地址:http://hyperledger-fabric.readthedocs.io/en/latest/fabric_model.html Hyperledger Fabric Model/ ...

  5. NIFI Site to Site 安全模式资料学习整合(均来自官网翻译)

    NIFI Site to Site 安全模式资料学习整合(均来自官网翻译) 官网连接:Apache NiFi 文档 概述-翻译官网 当发送数据从一个NIFI示例到另一个NIFI实例,此处可以使用很多不 ...

  6. Struts2官网翻译

    翻译一下Struts 2 官网,方便下载:跟踪最新技术等: http://struts.apache.org/ Apache Struts is a free, open-source, MVC fr ...

  7. 【官网翻译】性能篇(十)性能提示

    前言 本文翻译自Android开发者官网的一篇文档,主要用于介绍app开发中性能优化的一实践要点. 中国版官网原文地址为:https://developer.android.google.cn/tra ...

  8. spring官网翻译

    首页 这是spring官网的头部 Let's build a better Enterprise 让我们建立一个更好的企业. Spring helps development teams everyw ...

  9. 10-10-010-简介-官网-官网翻译

    1. 官网 Netty is an asynchronous event-driven network application framework for rapid development of m ...

最新文章

  1. FINDCONTROL的详细介绍
  2. 首次看清体内所有癌症转移灶,深度学习方法立大功!中国留学生一作论文登《细胞》封面...
  3. DedeCms如何调用Discuz论坛主题等数据方法总结
  4. Android 使用SWIG生成Jni代码转
  5. thymeleaf 中select下拉回显
  6. idea编译android模块,Android IntelliJ IDEA 14.1:模块没有主类
  7. Pulsar较Kafka的优势
  8. 2265. 统计值等于子树平均值的节点数
  9. 彩色图像和灰色图像的区别
  10. python绘制人物关系图,Python来袭,教你用Neo4j构建“复联4”人物关系图谱!
  11. 研究生留学资助项目突遭暂停,美国两大科研机构设限,上千访问学者或受影响...
  12. 火车采集器采集内容页分页教程
  13. dot全称_DOT是什么
  14. node.js学习笔记Day2
  15. 超强!Figma汉化版下载教程来了!
  16. Python3网络爬虫requests库保存登录cookies无法显示登录后的结果
  17. 魅族Android10内测招募答案,魅族flyme9内测招募答案
  18. 关于python安装问题 0x80072f7d的解决方法
  19. JAVA之翻转棋游戏
  20. 如何使用OBS 进行屏幕录制

热门文章

  1. java jpa 注解_Java : JPA相关以及常用注解
  2. java中datetime类型转换,Java中日期格式和其他类型转换详解
  3. java线程“生产/消费”模型2
  4. c++函数传参:值传递、指针传递、引用传递
  5. xp系统目前禁用索引服务器,WinXP系统中可以被禁用的服务对照表
  6. 从WebRtc学习RTCP协议
  7. 栈与队列在SGI STL的底层实现
  8. C++语法:vector的使用
  9. stl中copy()函数_std :: copy_if()函数以及C ++ STL中的示例
  10. kotlin 判断数字_Kotlin程序检查给定数字是正数,负数还是零