第一次接触knockout,就感觉和ng有太多神似!MVVM框架中Angular是好,但这么大而全的框架,学习难度可不低呢,上手起码也得要个一两周吧。而knockoutjs专注于数据绑定,只需一两天就可以投入使用了,学习成本不要太低!在前端进化如此迅速的时代,学习成本也是不得不考虑的一个因素。很多时候其实我们的项目并没那么复杂,也并不需要万能的框架,更需要的反而是简单顺手的工具。

Before Knockoutjs

假设我们做一个订单系统,需要显示商品单价,然后可以根据输入数量计算出总价并显示出来。使用原生代码也很容易实现,效果:

代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!--HTML code-->
Price: <span id= "price" ></span><br />
Account: <input type= "text" id= "account" value= "" placeholder= "请输入数量" /><br />
sum: <span id= "sum" ></span>
//js code
var priceNode = document.getElementById( 'price' ),
accountNode = document.getElementById( 'account' ),
sumNode = document.getElementById( 'sum' ),
price = 100,
account = 11,
sum = price * account;
//初始化。
priceNode.innerText = price;
accountNode.value = account;
sumNode.textContent = sum;
//监视 View层的用户输入
accountNode.addEventListener( 'keydown' , function (e) {
window.setTimeout( function () {
account = accountNode.value;
sum = price * account;
sumNode.textContent = sum;
},10);
});

嗯,蛮简单的!哦,对了,我们一次展示50件商品,同时又有10类这样的展示,还有买5盒冈本送一根油条这样的各种促销……

所以,你知道原生实现的问题了吧:
•随着 UI 和数据交互的增多,代码量迅速增长,难以维护
•基于 Dom 查询,id 或 class 的命名难以管理
•代码耦合度高,难以复用

Knockoutjs简介

Knockoutjs(下面简称ko)就是为了解决上述问题而出现的,他是一个轻量级的MVVM库,专注于实现数据与视图的绑定,本身并不提供 UI 类和路由等功能,上手非常快。同时,由于ko出来已经有些年头了,已经是比较成熟的框架了。在做一些动态显示比较多的页面时,ko无疑是一个比较好的选择。关于MVVM楼主就不多说了,一图以蔽之:

ko建立在3大核心特征之上(官网介绍):

1. 可观察对象与依赖跟踪 (Observables and dependency tracking):使用可观察对象在模型数据之间设立隐性关系链,用于数据转换和绑定。

2. 声明式绑定 (Declarative bindings):使用简单易读的语法方便地将模型数据与DOM元素绑定在一起。

3. 模板 (Templating):内置模板引擎、为你的模型数据快速编写复杂的 UI 展现。

使用ko非常简单,直接到官网(http://knockoutjs.com/index.html)下载并用<script>引入即可。

可观察对象

使用ko重写上面的例子(自定价格,这也是我小时候的愿望之一):

代码是这样的:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!--HTML Code-->
<div id= "one" >
Price: <input type= "text" data-bind= "value: price" placeholder= "请输入单价" /><br />
Account: <input type= "text" data-bind= "value: account" placeholder= "请输入个数" /><br />
sum: <span data-bind= "text: sum" ></span>
</div>
// js Code
var ViewModel = function (p, a) {
//设置为可观察对象并以参数p、a初始化
this .price = ko.observable(p);
this .account = ko.observable(a);
//调用ko函数的时候将this传入,否则执行ko.pureComputed内部代码时,this为ko,ko.price()报错。
this .sum = ko.pureComputed( function () {
//因为可观察对象是一个函数对象,所以要用 price()来读取当前值。
//设置值使用price(NewValue),支持链式写法:this.price(12).account(3)
return this .price() * this .account();
}, this );
};
var vm = new ViewModel(135, 10);
//应用该绑定,绑定开始生效
ko.applyBindings(vm);

1)先看HTML代码:

可以看到在每个标签中都加入了一个 data-bind = "XX:OO" 这样的键-值对。这个就是 ko 的绑定语法,XXOO代表什么东西呢?(XXOO?楼主还是个孩子啊…)从例子可以看到XX为标签的属性,可以是text、value、class、checked等标签属性,其实也可以是click、focus、load等DOM事件。OO看起来像是一个变量,实际上并不是变量,而是一个函数对象,执行这个函数(带个())就能得到相应的绑定值。通过XXOO就可以将元素的属性或事件跟js中的函数对象绑定在一起(XXOO了就要相互负责哈),这就是ko的声明式绑定。绑定的定义其实就是一个观察者模式,只不过这是双向的绑定,发布者和订阅者相互订阅了对方的消息而已,这就是MVVM的双向绑定。ko双向绑定的结果就是一方变化就可以自动更新另一方,也就是通过ViewModel将数据和表现层紧紧绑定在一起了。

2)再看看js代码:

可以看到js中定义了一个ViewModel对象,在对象中对HTML中绑定的OO进行了操作。这里主要有两个操作: ko.observable()和ko.pureComputed()。

•ko.observable(p):见名知义、这个就是设置可观察对象的方法,传入的参数p就是初始化的值,这里的参数可以是基本数据类型,也可以是一个json对象。被设置为可观察对象后就意味着系统会一直观察这个值。无论是ViewModel中的p还是被绑定对象的p发生变化都会引起刷新事件,将所有用到这个值的地方都更新到最新状态。显然,可观察对象是比较消耗性能的,所以对于不需要动态变更的值(如价格)则不要设置为可观察对象,当然还是需要放入ViewModel中进行集中初始化。

•注意:ko.observable(p)返回的可观察对象是一个函数对象,所以读取可观察对象需要使用price()这种方式;同样的,设置可观察对象需要使用price(newValue)这种方式。比较贴心的是,设置的时候支持链式写法:ViewModel.price(100).account(10)。

•ko.pureComputed()就是所谓的依赖跟踪了,这里是单价*数量等于总价,注意这里不能直接用this.sum = this.price() * this.account();来指定sum,这种写法不能动态刷新被绑定的对象,只是动态改变了sum变量,但要去刷新绑定对象还需要其他操作。所以,与计算相关的绑定值都要用ko的计算函数来设置。当然,返回的也是一个函数对象。另外,ko还有一个computed函数,也可以用其来进行设置,不过推荐使用pure的方式,以提高性能。

•注意这里的写法:ko.pureComputed(fn, this),也就是将fn绑定到ViewModel作用域中,其实就是js中的call/apply。因为在执行ko内部函数的时候,this为ko对象,所以为了得到ViewModel对象的作用域,需要通过上面的写法传入this。当然也可以在ko函数外部用that保存ViewModel对象,然后在ko函数内部使用that来调用ViewModel对象。像这样:

?
1
2
3
4
var that = this ;
this .sum = ko.pureComputed( function () {
return that.price() * that.account();
});

定义好ViewModel构造函数后便实例化了一个ViewModel对象,然后使用了ko.applyBindings()的方式来使得绑定生效,这一步不要漏掉了。

使用ko的页面简单模式:

?
1
2
3
4
5
6
7
<!--HTML Code-->
<span data-bind= "text: bindtext" ></span>
// js Code
var viewModel = {
bindtext: ko.observable( 'initValue' )
};
ko.applyBindings(viewModel);

总结起来就是:HTML中使用data-bind="XX: OO"声明绑定,js中建立ViewModel并设置可观察对象,最后应用绑定。

可观察对象数组

再看看可观察对象数组的使用方法,在ko中可不能像js一样数组和变量混用,对于数组对象就要用ko.observableArray([…,…])这种形式,同样的,数组元素也可以是基本类型也可以是json对象。ko中的可观察对象数组有一系列的数组操作方法,如slice()、sort()、push()这种,效果跟原生的js数组操作方法一样,只是通过ko方法所做的改动会通知到订阅者从而刷新界面,但js方法则不会刷新界面。下面是一个简单例子:

?
1
2
3
4
5
6
7
8
<!--HTML Code-->
<select data-bind= "options: list" ></select>
// js Code
var vm = {
// list: ko.observableArray()
list: ko.observableArray([ 'Luffy' , 'Zoro' , 'Sanji' ])
};
ko.applyBindings(vm);

关键点:ko监控的是数组的状态,而不是元素本身的状态。也就是说当数组状态变化(增减元素)的时候会触发ko事件引起绑定对象的刷新,但数组内部元素的变化(如:值变化)则不被监控不能触发ko事件。例如:

在控制台中使用原生方法将Luffy动态改成Lucy是不会刷新UI页面的,而使用ko的数组操作改动数组则会立即刷新页面,值得注意的是在刷新的时候,也会将之前的改动刷新出来(Luffy > Lucy)。也就是说其实js内存中的变量是已经改变了,但是还缺少一个刷新DOM的动作。这里大家可以看到,读取数组的方法是vm.list()[0],因为list也是一个函数对象,执行返回值才是我们想要的list内容。同理,也可以通过 vm.list(["妹子","妹子","妹子"]) 这样的方式重置可观察对象数组,也能立即刷新UI。

如果需要将数组元素的改动也动态反应到UI上,需要将数组元素也设置为可观察对象,然后使用ko的方法改变数组元素值。注意,是使用ko的方法 list()[0]("Lucy")!

操作可观察对象数组的方法有两类,一类是与原生js数组方法同名的:pop, push, shift, unshift, reverse, sort, splice,这一部分与js原生方法的用法和效果都一样,就不再赘述了。

总结

本篇主要简单介绍了knockoutjs中最重要的概念:可观察对象(数组)。可观察对象实质上是一个函数对象,通过ko方法操作可观察对象时可以动态刷新UI展现,这个是推荐做法。同时,也可以通过原生的js方法操作可观察对象,只是原生方法并不会刷新UI展现,需要等到下一次刷新事件时才会被刷新到UI中。

转载于:https://www.cnblogs.com/liuHz17/p/9317972.html

knockout学习第一步相关推荐

  1. UNP学习第一步:unp.h的安装及第一个程序的运行

    UNP学习第一步:unp.h的安装及第一个程序的运行 unp.h的安装 源代码编译 静态库安装 运行第一个程序 启动daytime服务 unp.h的安装 源代码编译 在书籍网站(http://www. ...

  2. python安装包_迈出Python学习第一步:Python开发环境的下载与安装

    所谓"磨刀不误砍柴工"."工欲善其事,必先利其器",都在告诉我们一个道理:要做好一个事情,事先做好充分的准备工作是非常重要的.所以在我们正式学习用Python编 ...

  3. HTML 学习 第一步内容

    为什么80%的码农都做不了架构师?>>>    加油,HTML 虽然很多标签,不过用用就习惯了.很快就能maste ! HTML 是原始内容和浏览器沟通的方式.把原始内容组织成为HT ...

  4. 学习java第一步_Spring Boot 学习第一步(搭建初步环境)

    学习一个东西的第一步是要学会如何迅速搭建起来一个可用的环境,也就是demo.这里我选择的开发环境是Eclipse, Maven + Spring Web 项目结构在Eclipse下面的实现 我们在这里 ...

  5. Spring Boot 学习第一步(搭建初步环境)

    学习一个东西的第一步是要学会如何迅速搭建起来一个可用的环境,也就是demo.这里我选择的开发环境是Eclipse, Maven + Spring Web 项目结构在Eclipse下面的实现 我们在这里 ...

  6. 深度学习第一步(anaconda、pytorch安装)

    不讲太多序言,做个无趣的男孩子,上来就上干货 第一步:anaconda安装 1.首先下载anaconda 官网咱们就不说了,下载慢,还容易出问题 直接上国内好资源,在清华镜像源下载安装包 anacon ...

  7. JAVA学习第一步-配置JAVA开发环境和学习资料

    写代码配置开发环境非常重要 java开发环境配置 1 windows中环境配置 1.1 JDK工具包 1.2 IDEA 1.3 eclipse安装 2 Linux下安装 2.1 VMware虚拟机 2 ...

  8. caffe windows 学习第一步:编译和安装(vs2012+win 64)

    转载自:http://www.cnblogs.com/denny402/p/5041060.html 没有GPU,没有linux, 只好装caffe的windows版本了. 我的系统是win10(64 ...

  9. RocketMQ学习第一步之源码构建

    这里写目录标题 绪论 源码构建 1.clone 2. 构建 3.配置 3.1配置namesrv 3.2新建文件夹 3.3 配置broker 3.4 配置producer 3.5 配置 consumer ...

最新文章

  1. 数据仓库与联机分析处理
  2. C#枚举中的位运算权限分配浅谈
  3. pmp考试中容易混淆的22组概念
  4. 详解XStream别名
  5. Apache Camel 2.20发布–新增功能
  6. Makefile(一)
  7. 15个优雅的Python编程技巧,掌握后瞬间玩转Python
  8. keras如何在验证集加噪声_Keras从时域、频域处理音频分类问题(带详细注释)...
  9. linux禁用ssh弱加密算法,SSHSSL弱加密算法漏洞修复
  10. KVM 介绍(1):简介及安装
  11. html5电商销售网站统计后台模板html5电商销售网站统计后台模板
  12. 查看树莓派引脚以及串口连接
  13. vulhub-靶场实战-安装
  14. IEEEtran模板使用Bibtex插入DOI不显示问题
  15. 企业10大HR软件分析对比(精)
  16. 如何在windows电脑网页上创建苹果ID?
  17. 论文 PPT 画图导出 PDF 注意事项
  18. uni.app开发物联网小程序
  19. java纯后台实现Excel导出
  20. 公民SF证号码的构成

热门文章

  1. 【蓝桥杯嵌入式】第十二届蓝桥杯嵌入式省赛客观题及详细题解
  2. away3d 4x的阴影方法们
  3. Android开发之推送服务(三) 集成Oppo和vivo推送
  4. 48. SSRF篇——SSRF原理+利用+防御
  5. 如何清除公众号H5页面缓存
  6. 2020熔化焊接与热切割证考试及熔化焊接与热切割作业考试题库
  7. SQLServer Delayed durability 延迟持久化
  8. 阿里云怎样配置数据库服务器配置?
  9. VSCode 注释快捷键
  10. 如何编写一个完整的Linux命令