Knockoutjs官网翻译系列(一)

       最近马上要开始一个新项目的研发,作为第一次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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/395749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django之静态文件配置

静态文件 了解静态文件配置之前&#xff0c;我们需要知道静态文件是什么&#xff1f; 静态文件其实指的是像css,js&#xff0c;img等一些被模板需要的文件。 如何在Django中配置我们的静态文件 1.建立static文件夹&#xff0c;将静态文件放在该目录下 2.在settings文件下配置如…

神奇的图像处理算法

http://blog.chinaunix.net/uid-23065002-id-4392043.html http://blog.csdn.net/k_shmily/article/details/51138154 几周前&#xff0c;我介绍了相似图片搜索。 这是利用数学算法&#xff0c;进行高难度图像处理的一个例子。事实上&#xff0c;图像处理的数学算法&#xff0c…

JavaWeb项目前端规范(采用命名空间使js深度解耦合)

没有规矩不成方圆&#xff0c;一个优秀的代码架构不仅易于开发和维护&#xff0c;而且是一门管理与执行的艺术。 这几年来经历了很多项目&#xff0c;对代码之间的强耦合及书写不规范&#xff0c;维护性差等问题深恶痛绝。在这里&#xff0c;通过仔细分析后&#xff0c;结合自己…

PCB genesis自制孔点 Font字体实现方法

一.先看genesis原有Font字体 在PCB工程CAM加孔点字体要求时,通常我们直接用Geneis软件给我们提供了2种孔点字体canned_57与canned_67,但此字体可能不能满足各个工厂个性化需求&#xff0c;比如&#xff1a;孔密度&#xff0c;孔间距&#xff0c;孔形状分布&#xff0c;如果有一…

Google 最新的 Fuchsia OS【科技讯息摘要】

转自&#xff1a;http://www.cnblogs.com/pied/p/5771782.html 就是看到篇报道&#xff0c;有点好奇&#xff0c;就去FQ挖了点东西回来。 我似乎已开始就抓到了重点&#xff0c;没错&#xff0c;就是 LK 。 LK 是 Travis Geiselbrecht 写的一个针对 ARM 的嵌入式操作系统&#…

pandas:根据行间差值进行数据合并

1. 问题描述 在处理用户上网数据时&#xff0c;用户的上网行为数据之间存在时间间隔&#xff0c;按照实际情况&#xff0c;若时间间隔小于阈值&#xff08;next_access_time_app&#xff09;&#xff0c;则可把这几条上网行为合并为一条行为数据&#xff1b;若时间间隔大于阈值…

java8的路径_什么是路径?

# 什么是路径&#xff1f;文件系统以某种形式的媒体(通常为一个或多个硬盘驱动器)存储和组织文件&#xff0c;使得它们可以容易地被检索。目前使用的大多数文件系统将文件存储在树形(或分层)结构中。在树的顶部是一个(或多个)根节点。在根节点下&#xff0c;有文件和目录(Micro…

解析su,su -,sudo的区别

2019独角兽企业重金招聘Python工程师标准>>> 本人以前一直习惯直接使用root&#xff0c;很少使用su&#xff0c;前几天才发现su与su -命令是有着本质区别的&#xff01; 大部分Linux发行版的默认账户是普通用户&#xff0c;而更改系统文件或者执行某些命令&#xff…

java maven 操作 收集的一些命令

maven打包&#xff1a; mvn clean package -Dmaven.test.skiptrue 运行jar: java -jar target/spring-boot-scheduler-1.0.0.jar 这种方式关掉控制台就不可以访问&#xff0c;现在要后台运行的方式启动 nohup java -jar target/spring-boot-scheduler-1.0.0.jar & 清理并…

java犯的小错误_[Java教程]十个JavaScript中易犯的小错误,你中了几枪?

[Java教程]十个JavaScript中易犯的小错误&#xff0c;你中了几枪&#xff1f;0 2015-06-01 12:00:19序言在今天&#xff0c;JavaScript已经成为了网页编辑的核心。尤其是过去的几年&#xff0c;互联网见证了在SPA开发、图形处理、交互等方面大量JS库的出现。如果初次打交道&…

Kali渗透测试——利用metasploit攻击靶机WinXP SP1

搭建渗透测试环境 Kali攻击机 WinXP SP1 靶机 启动metasploit 跟windows RPC相关的漏洞 内部提供的漏洞攻击 靶机winxp sp1网络配置 查看虚拟机的NAT网段 配置WinXP SP1靶机的IP地址 执行漏洞利用 后漏洞利用&#xff1a;meterpreter> 靶机的信息 进程情况 查看到explorer.e…

创建响应式布局的优秀网格工具集锦《系列五》

在这篇文章中&#xff0c;我们为您呈现了一组优秀的网格工具清单。如果网页设计和开人员采用了正确的工具集&#xff0c;并基于一个灵活的网格架构&#xff0c;以及能够把响应图像应用到到设计之中&#xff0c;那么创建一个具备响应式的网站并不一定是一项艰巨的任务。enjoy! 您…

java 无侵入监控_MyPerf4J 一个高性能、无侵入的Java性能监控和统计工具

MyPerf4J一个针对高并发、低延迟应用设计的高性能且无侵入的实时Java性能监控和统计工具。 受 perf4j 和 TProfiler启发而来。MyPerf4J具有以下几个特性&#xff1a;无侵入: 采用JavaAgent方式&#xff0c;对应用程序完全无侵入&#xff0c;无需修改应用代码高性能: 性能消耗非…

javascript 减少回流

减少回流&#xff08;REFLOWS&#xff09; 当浏览器重新渲染文档中的元素时需要 重新计算它们的位置和几何形状&#xff0c;我们称之为回流。回流会阻塞用户在浏览器中的操作&#xff0c;因此理解提升回流时间是非常有帮助的。 回流时间图表 你应该批量地触发回流或重绘&#x…

转: 关于 ssl的建立链接的过程

转自&#xff1a; http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html SSL/TLS协议运行机制的概述 作者&#xff1a; 阮一峰 日期&#xff1a; 2014年2月 5日 互联网的通信安全&#xff0c;建立在SSL/TLS协议之上。 本文简要介绍SSL/TLS协议的运行机制。文章的重点是设计思…

PHP 文件加密Zend Guard Loader 学习和使用(如何安装ioncube扩展对PHP代码加密)

一、大体流程图 二、PHP 项目文件加密 下表列出了Zend产品中的PHP版本及其内部API版本和Zend产品版本。 如何加密请往后看 三、如何使用 第一步&#xff1a;确认当前环境 Amai Phalcon 前&#xff0c;请确认您具备以下两个条件&#xff0c;如果您的环境不满足此条件&#xff0c…

php寻找文本,PHP文本数据库的搜索方法_php

//php文本数据库的搜索方法searchstr("/".preg_quote($searchstr)."/");//$searchstr是查找的关键字$recordsfile($file);//获取所有的记录数http://www.gaodaima.com/45906.htmlPHP文本数据库的搜索方法_php//$file是查找的数据文件$search_reocrdspreg_g…

bzoj 2178 圆的面积并 —— 辛普森积分

题目&#xff1a;https://www.lydsy.com/JudgeOnline/problem.php?id2178 先看到这篇博客&#xff1a;https://www.cnblogs.com/heisenberg-/p/6740654.html 好像本应算弓形面积、三角形面积之类的&#xff0c;但不会...于是用辛普森积分硬做... 参考了这篇博客&#xff1a;ht…

Charles抓包工具的使用

2019独角兽企业重金招聘Python工程师标准>>> 感谢唐巧分享的文章&#xff0c;受益匪浅 文章目录 1. 目录及更新说明2. Charles 限时优惠3. 简介4. 安装 Charles5. 将 Charles 设置成系统代理6. Charles 主界面介绍7. 过滤网络请求8. 截取 iPhone 上的网络封包 8.1. …

iOS开发——处理1000张图片的内存优化

一、项目需求 在实际项目中&#xff0c;用户在上传图片时&#xff0c;有时会一次性上传大量的图片。在上传图片前&#xff0c;我们要进行一系列操作&#xff0c;比如&#xff1a;旋转图片为正确方向&#xff0c;压缩图片等&#xff0c;这些操作需要将图片加载到内存中&#xff…