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,一经查实,立即删除!

相关文章

无人机导航定位系统Java_无人机高精度室内定位导航的技术方案

原标题&#xff1a;无人机高精度室内定位导航的技术方案因为一些特殊的用途&#xff0c;比如室内表演&#xff0c;编队室内飞行等&#xff0c;无人机不可避免会在室内飞行&#xff0c;无人机对室内定位精度的要求很高&#xff0c;室内空间本身就不会太大&#xff0c;若定位精度…

javascript控制台_如何充分利用JavaScript控制台

javascript控制台by Darryl Pargeter达里尔帕格特(Darryl Pargeter) 如何充分利用JavaScript控制台 (How to get the most out of the JavaScript console) One of the most basic debugging tools in JavaScript is console.log(). The console comes with several other use…

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;结合自己…

java重要基础知识点_java基础知识点整理

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼java基础知识点整理1.&和&&的区别&#xff1f;&&#xff1a;逻辑与(and),运算符两边的表达式均为true时&#xff0c;整个结果才为true。&&&#xff1a;短路与&#xff0c;如果第一个表达式为false时&#…

网易云音乐的算法有什么特点_当算法设计音乐厅时会发生什么?

网易云音乐的算法有什么特点Here are three links worth your time:这是三个值得您花费时间的链接&#xff1a; What happens when algorithms design a concert hall? (3 minute read) 当算法设计音乐厅时会发生什么&#xff1f; ( 阅读3分钟 ) How to land a top-notch tec…

开机发现超级管理员账户不见了

今天出现了一个怪现象&#xff0c;连接打印机的电脑上没有超级管理员账户&#xff0c;只有一个刚建立的新账户&#xff0c;这是怎们回事来&#xff1f;嗳&#xff0c;原来啊&#xff0c;安装Windows XP时&#xff0c;如果又设置了一个管理员账户&#xff0c;那么系统内置没有密…

vs自带iis局域网调试

http://www.cnblogs.com/liluping860122/p/4685564.html转载于:https://www.cnblogs.com/wcLT/p/5594252.html

java.util.set cannot be assigned from null_Java中有关Null的9件事

对于Java程序员来说&#xff0c;null是令人头痛的东西。时常会受到空指针异常(NPE)的骚扰。连Java的发明者都承认这是他的一项巨大失误。Java为什么要保留null呢&#xff1f;null出现有一段时间了&#xff0c;并且我认为Java发明者知道null与它解决的问题相比带来了更多的麻烦&…

node.js事件驱动_了解Node.js事件驱动架构

node.js事件驱动by Samer Buna通过Samer Buna 了解Node.js事件驱动架构 (Understanding Node.js Event-Driven Architecture) Update: This article is now part of my book “Node.js Beyond The Basics”.更新&#xff1a;这篇文章现在是我的书《超越基础的Node.js》的一部分…

如何基于 Notadd 构建 API (Laravel 写 API)

如何基于 Notadd 构建 API Notadd 底层实现了 passport 机制&#xff0c;有统一的授权管理&#xff0c;主要支持两种方式进行 API 授权&#xff0c;一个是 client&#xff0c;领一个是 passport&#xff0c;这个在其他文档中有做详细的说明。 这里主要说的是&#xff0c;如何基…

mysql 基于集_一种基于记录集查找特定行的方法_MySQL

问&#xff1a;我的一个表中包含了名为IdValue的单列主键。对于给定的IdValue值&#xff0c;我希望找到紧邻目标值之前和之后的表行(假定结果按IdValue排序)。怎样才能不使用游标而通过一个基于集合的方法得到需要的结果&#xff1f;答&#xff1a;Transact-SQL是一个基于集合的…

react 交互_如何在React中建立动画微交互

react 交互Microinteractions guide a user through your application. They reinforce your user experience and provide delight.微交互引导用户完成您的应用程序。 它们可以增强您的用户体验并带来愉悦感。 You may have seen some of the slick examples of microinterac…

HTTPS与MITM

HTTPS:基于SSL/TSL的HTTP协议 MITM:Man-In-The-Middle中间人攻击 Https下中间人攻击的思路&#xff1a; 1 去https化 2 向CA申请相似域名的证书 防范&#xff1a; 睁大双眼转载于:https://www.cnblogs.com/the-owl/p/5596254.html

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 的嵌入式操作系统&#…

java 03_Java基础03—流程控制

流程控制参考资料&#xff1a;《Java从入门到精通》/明日科技编著. 4版. 北京&#xff1a;清华大学出版社&#xff0c;2016一、复合语句Java的复合语句由“{”开始&#xff0c;“}”结束&#xff0c;又称为块语句。复合语句都是由上至下被执行&#xff1b;复合语句中可以嵌套复…

这三种策略可以帮助女性在科技领域蓬勃发展

by Shubhi Asthana通过Shubhi Asthana 这三种策略可以帮助女性在科技领域蓬勃发展 (These 3 strategies can help women thrive in tech) As someone early on in her career, I’ve attended a few tech talks, conferences, and meetups. One thing I noticed is not many w…

手机卫士09_应用程序四种查看_ListView小标题_进程管理

手机卫士09_应用程序四种查看_ListView小标题_进程管理 1.悬浮窗体的功能实现: 1.1.应用程序的卸载: 包安装器 packageInstall,包卸载packageruninstall intent.setData(Uri.pare(“package:” 应用程序包名)) 卸载完之后记得更新list集合,更新适配器. 但是不确定用户是否点了…