由于工作需要,接触到了Knockout,但是之前对于前台开发真的是不太了解,只能是摸着石头过河,边学边实践了。

Knockout的官方网站是:http://knockoutjs.com/。我也是跟着官网上的文档一步步学习。

本篇文章中的测试主要就是依据官网文档中的Creating view models with observables部分来进行的。

首先,我依照创建view model的方式,在js文件中创建了自己的view model:

 var myViewModel = {
name: "Yuki Nagato",
age: 15
};

随后在相应的html文件中写了些简短的测试段落:

 <body>
<h3>My test for knockoutJs(I don't know if it is right to write like this, haha)</h3>
<p>Test start:<span data-bind="text: name"></span></p>
</body>

此时如果直接在浏览器中浏览html文件的话是不会看到任何结果的,还需要激活Knockout,按照官网的说法,就是Activating Knockout,于是在js文件后又添加了新的一行:

 ko.applyBindings(myViewModel);

嗯,由于博主对于js的知识了解的真的很少,此时就直接想在浏览器中看到效果,结果页面显示如下:

而chrome的developer tools中显示:

于是在stackoverflow中找到了相应的问题,发现是这样一个问题:

提问者在这里采用的是在html文件中的script元素内添加defer属性的方式,这种属性我之前并没有见过,可以留作以后研究,但是另一种解决方式似乎更具有普遍性。现在jQuery的使用频率很高,jQuery中的ready部分详细描述了在使用jQuery的同时解决这种DOM与script载入顺序的方法,具体的文档在http://api.jquery.com/ready/。ready的作用在于指定相应的javascript function在DOM完全载入成功以后执行,javascript中似乎提供的是load事件,可以留作以后研究。

按照文档中的描述,有三种编写方式:

  • $( document ).ready( handler )
  • $().ready( handler ) (这种方式不推荐)
  • $( handler )

显然第三种方式最为简便,所以通用性也更强,一般的格式如下:

 $(function() {
// Handler for .ready() called.
});

当然,文档中还提到了onload属性和ready的兼容性问题以及jQuery的命名空间问题,由于不涉及我现在要用的东西,可以留作以后研究。

这样一来,我的js文件就变成了这样:

 $(function() {
var myViewModel = {
name: "Yuki Nagato",
age: 15
}; ko.applyBindings(myViewModel);
});

当然,我也在html文件中添加了jQuery文件的链接,而浏览器中也成功显示出了view model中的name属性:

而在Knockout的文档中也提到说ko.applyBindings这个函数的参数可以有两个,第一个用于声明你用来激活declarative bingdings的view model,第二个则可以通过指定相应的selector来选择性的绑定view model,这里我做了一个测试,将html文件改成这样:

 <p>Name: <span id="name" data-bind="text: name"></span></p>
<p>Age: <span data-bind="text: age"></span></p>

js文件则改成了这样:

 ko.applyBindings(myViewModel, document.getElementById("name"));

随后页面显示如下:

可以看到,我们仅仅激活了相应ID的元素,不知道选取DOM node能不能通过jQuery的方式,应该会更为简便一些。

之前的例子里,我仅仅是在页面中展现了view model的属性,但KO的关键优势就在于它能够根据view model的变化来自动更新UI(页面)的变化。为了能让KO知晓view model的变化,我们需要在view model中将相应的属性声明为observable,它是一种特殊的能够通知订阅者相应的改变,并能够自动探测相应的依赖关系的javascript object。于是,我的js文件更新如下:

 $(function() {
var myViewModel = {
name: ko.observable("Yuki Nagato"),
age: ko.observable(15)
}; ko.applyBindings(myViewModel);
});

而获取或是修改observable的值也是极为方便的,在js文件中添加如下几行:

 myViewModel.age(20);
var name = myViewModel.name();
$("#getValueOfOB").text(name);

在html文件中再添加一个p元素:

 <p>Test for getting the value of observable: <span id="getValueOfOB"></span></p>

这是可以在页面中看到相应的效果:

可以看出js中对view model修改的代码与applybindings之间的顺序没有没什么关系,在其之前其之后都可行。同时也可以采用链式语法来修改多个view model属性:

 myViewModel.name("Kazusa Touma").age(16);

当然,也可以自己定义相应的function来响应observable的变化,最简单的例子如下:

 myViewModel.name.subscribe(function(newName) {
  alert("The new name is " + newName);
});
myViewModel.name("Chiaki Izumi"););

需要注意的是,对相应observable的修改应当在自定义的subscribe function之后出现。而subscribe function可以接受三个参数,第一个是callback,作为observable改变时的相应处理;第二个是target(optional),可以指定callback function中的"this"的值;第三个是event(optional, default is "change"),作为callback function所需要响应的事件类型。

比如,我们可以将event更改为"beforeChange",即在observable更改之前进行自定义的操作,代码和页面显示如下:

 var mySubscription = myViewModel.name.subscribe(function(oldName) {
  alert("The old name is " + oldName);
}, null, "beforeChange");

当然,我们自己也可以终止自定义的subscription:

 var mySubscription = myViewModel.name.subscribe(function(newName) {
  alert("The new name is " + newName);
});
mySubscription.dispose();

这样一来,之后对observable的修改并不会触发我们自定义的subscribe function。

最后,该部分的文档也提到说我们可以强制订阅observable相应的改变(即便新的值和原先的值一样也会提醒),为了测试这一功能,我采用了自定义的subscribe function:

 var myBeforeSubscription = myViewModel.name.subscribe(function(oldName) {
  alert("The old name is " + oldName);
}, null, "beforeChange"); var mySubscription = myViewModel.name.subscribe(function(newName) {
  alert("The new name is " + newName);
}); myViewModel.name.extend({ notify: "always" }); myViewModel.name("Kazusa Touma");

我们可以看到页面产生这样的结果:

另外,通过extend方法,我们也可以为订阅设定一个延时:

 myViewModel.name.extend({ rateLimit: 5000 });

需要注意的是,这个延时是更改的延时,也就是将view model同步到UI的时间上的延时,而对于针对"beforeChange"事件的自定义subscribe function,它们会直接触发(不会涉及延时)。比如说我将延时设置为5秒,并且设定了两个自定义的subscribe function,一个的event是"beforeChange",另一个event是默认的"change",在页面载入后,beforeChange的function会直接执行,而change的function则会在5秒之后执行。

KnockoutJs学习笔记(一)的更多相关文章

  1. KnockoutJs学习笔记(五)

    作为一名初学者来说,一篇篇的按顺序看官网上的文档的确是一件很痛苦的事情,毕竟它的排列也并非是由浅及深的排列,其中的顺序也颇耐人寻味,于是这篇文章我又跳过了Reference部分,进而进入到具体的bin ...

  2. knockoutJS学习笔记01:从拼接字符串到编写模板引擎

    开篇 关于knockout的文章,园里已经有很多大神写过了,而且都写得很好.其实knockout学习起来还是很容易的,看看官网的demo和园里的文章,练习练习就可以上手了(仅限使用,不包含研究源码). ...

  3. knockoutJS学习笔记02:jsRender模板引擎

    上一篇最后提到了模板,并尝试自己编写一个最简单版本:有些朋友可能用过 jqtmpl,这是一个基于jquery的模板引擎,不过它已经不再更新了,而且据说渲染速度比较慢.这里介绍另外一个模板引擎:jsRe ...

  4. knockoutJS学习笔记03:knockout简介

    通常来说,前端的维护难度是比较大的,特别是脚本,虽然像jquery这样的库可以帮助我们减少很多代码,但在稍微复杂的情况下,还是会产生有很多代码.上一篇介绍了模板引擎jsRender,它可以帮我们快速生 ...

  5. knockoutJS学习笔记06:ko数组与模板绑定

    前面已经介绍了基本的绑定和模板相关知识,接下来就看ko里的数组和模板绑定,数组和模板绑定应该是实际项目中用得比较多的,ko提供了很好的支持. 一.observaleArray 前面的监控属性都是单个对 ...

  6. KnockoutJS学习笔记10:KonckoutJS foreach绑定

      KnockoutJS foreach绑定用来处理数组,通常用来将一个数组绑定到一个列表或者table中.在foreach绑定中,我们可以使用if.with等嵌套绑定. 示例代码: <tabl ...

  7. KnockoutJs学习笔记(九)

    由于component binding部分的内容更为复杂一些,所以这部分我暂时跳过,先学习click binding部分. click binding不仅可以作用于button.input.a等元素, ...

  8. KnockoutJs学习笔记

    1.缘由 新公司前端用的是Jquery+Knockout,Knockout只知道是MVVM,未曾接触.报到前,先学习下. 2.前置知识 MVVM模式介绍 MVVM:模型-视图-视图模型(Model-V ...

  9. KnockoutJs学习笔记(四)

    由于Writable computed observables和How dependency tracking works的要求相对较高,我先跳过这两篇,学习Pure computed observa ...

随机推荐

  1. 【Asp.net入门03】第一个ASP.NET 应用程序-创建ASP.NET项目

    本部分主要内容: 创建并运行Asp.net项目 web窗体 数据模型 调用代码隐藏方法 数据验证 1.操作步骤 第一步:启动Visual Studio 2013,然后从File(文件)菜单中选择New ...

  2. openssl md5 sha256 rsa des

    原文地址找不到了 #include <windows.h>#include <iostream>#include <cassert> #include <st ...

  3. P2158 [SDOI2008]仪仗队 && 欧拉函数

    P2158 [SDOI2008]仪仗队 题目描述 作为体育委员,C君负责这次运动会仪仗队的训练.仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线 ...

  4. ArcGis10.1 Feature Class Properties无法编辑

    被这个问题困扰了很久,最后从官网帮助中查询到资料解决了 先看一下截图: 这种问题一般是FratureClass被锁,被mxd引用,并且发布服务有实例在运行,但我新创建一个FeatureClass也无法 ...

  5. Nginx upstream的5种权重分配方式【转】

    原文地址:Nginx upstream的5种权重分配方式 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除. 2.weight指定轮询几率,weig ...

  6. 针对用户在个人中心绑定手机认证的一些js代码。

    需求: 1:手机号码校验(格式的校验,手机号码是否已经绑定过)---未实现 2:填完手机号码,点击发送验证码,手机会收到一条信息 3:发送验证码按钮不可用,变成重新发送的倒计时 1):60秒以后又可以 ...

  7. Python概念-反射之文化底蕴版:反正射了

    什么是反射 光在两种物质分界面上改变传播方向又返回原来物质中的现象,叫反射! 以上,是反射的物理定义,与python中的反射概念,完全没有任何关系 书归正传:反射 就是通过字符串的形式,操作对象相关的 ...

  8. Java并发编程(4)--生产者与消费者模式介绍

    一.前言 这种模式在生活是最常见的,那么它的场景是什么样的呢? 下面是我假象的,假设有一个仓库,仓库有一个生产者和一个消费者,消费者过来消费的时候会检测仓库中是否有库存,如果没有了则等待生产,如果有就 ...

  9. 工具推荐:ATSCAN,功能强大的Perl脚本扫描器

    工具推荐:ATSCAN,功能强大的Perl脚本扫描器 使用perl语言编写的开源的扫描器,功能丰富强大,除了基本的tcp和udp端口扫描之外,还可以搜索wordpress.joomla等网站并进行口令 ...

  10. Strusts2笔记7--国际化

    国际化: 国际化是指,使程序在不做任何修改的情况下,就可以使用在不同的语言环境中.国际化在一般性项目中是不常用的.在编程中简称 i18n. 国际化是通过读取资源文件的形式实现的.资源文件的定义与注册, ...