Knockoutjs 学习系列(二)花式捆绑


Posted in Javascript onJune 07, 2016

在上一篇Knockoutjs 学习系列(一)ko初体验文章中提到,ko中的 data-bind = "XX:OO"绑定大法除了可以绑定text、value等内容,还可以绑定visible、style等外观属性,也可以绑定click、textInput等各种事件,甚至还能控制程序流程。各种花式捆绑,绝对满足你的幻想。

下面简单讲讲各种绑定的使用,主要根据被绑定的属性分成表现类、流程类和交互类三种。

表现类属性

表现类的绑定属性有visible、text、html、css、style、attr几种,除了css表示css的class之外,其他都很好理解。当然了,style里面的命名要与js一致,要去掉-改成驼峰命名,示范如下:

<!--HTML code-->
<div data-bind="visible: shouldShowMessage">You will see this message only when "shouldShowMessage" holds a true value.</div>
<div>Today's message is: <span data-bind="text: myMessage"></span></div>
<div data-bind="html: details"></div>
<div data-bind="css: { profitWarning: currentProfit() < 0 }">CSS class binding test</div>
<div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }">CSS style binding test</div>
<a data-bind="attr: { href: url, title: urltitle }">Report</a> 
// js code
var viewModel = {
shouldShowMessage: ko.observable(true), // Message initially visible
myMessage: ko.observable(), // Initially blank
details: ko.observable(), // Initially blank
currentProfit: ko.observable(150000), // Positive value, so initially we don't apply the "profitWarning" class
currentProfit: ko.observable(150000), // Positive value, so initially black
url: ko.observable("year-end.html"),
urltitle: ko.observable("Report including final year-end statistics")
};
ko.applyBindings(viewModel); // apply binds

效果是这样的:

Knockoutjs 学习系列(二)花式捆绑

表现类的设置比较简单,要注意的一点就是:很多表现类的属性并不需要动态变化,这个时候可以利用viewModel中设置实现数据的集中初始化,但是不要把他们设置成可观察者,如:

// js code
var viewModel = {
shouldShowMessage: ko.observable(true), // Message initially visible
myMessage: '这段文字不需要动态更新' // Initially blank
};

流程类属性

流程类包括foreach、if、ifnot、with和比较高级的"component”绑定,if 和 ifnot 与 visible类似,差别就是:if 会直接从DOM中移除相应的组件,而visible只是控制隐藏显示,组件还是在DOM里面的。with 跟 js 中的 with 也是一样的效果,就是延长了作用域链,简单的来说就是在变量前加了个'前缀.'。这里只介绍一下foreach,component放到和模板绑定一起介绍。

Knockoutjs 学习系列(二)花式捆绑

看看代码:

<!--HTML code-->
<p>测试foreach绑定</p>
<ul data-bind="foreach: people">
<li>
No.<span data-bind="text: $index"> </span>
people's name: <span data-bind="text: name"> </span>
<a href="#" data-bind="click: $parent.removePeople">RemovePeople</a>
<a href="#" data-bind="click: remove">Remove</a>
</li>
</ul>
<input type="button" data-bind="click: addPeople" value="Add" /> 
var listModel = function () {
//设置people数组的值(people实际上是函数数组),使用foreach可以遍历数组对象
//ul,li对应的是 people和people的子项,所以在li内部绑定时,作用域是在people子项{name……}中,为了调用people外部的removePeople需要用到$parent
//如果是调用内部的remove,remove中的this为{name……}对应当前li项,作用域为当前域则不用加 $parent。
this.people = ko.observableArray([
{name: "Mark Zake", remove: function () {
that.people.remove(this); //注意当前对象(就是{name……})和作用域,不用管HTML标签,纯js理解就简单了
}},
{name: "James Lebo", remove: function () {
that.people.remove(this);
}},
{name: "Green Deny", remove: function () {
that.people.remove(this);
}}
]);
//addPeople内部调用了同级people的方法,this会发生改变,应该预先保存this传进去。
var that = this;
this.addPeople = function () {
that.people.push({
name: new Date().toDateString(),
remove: function () {
that.people.remove(this);
}});
};
//remove的对象是整个 li标签,也就是 a标签的父对象。实际上要执行的是 listModel.people.remove(a.parent)
this.removePeople = function() {
that.people.remove(this);
}
};
ko.applyBindings(new listModel());

这里比较容易搞混的是DOM节点与ViewModel的层次对应关系。首先,在ul上应用 foreach 绑定,也就是每个 li 对应每个 people 子项。这一点对应上了之后,就按照 js 的作用域规则去理解即可。说到作用域,不得不提 this,正所谓我待this如初恋,this坑我千百遍。这里小茄在官方版本上加了个remove函数,与官方的removePeople对应起来看就简单了。至于$index, $parent这些变量,按字面意思理解即可。

交互类属性

终于要到重点了,使用ko的最重要原因就是为了处理动态交互的UI展现问题,这里集中介绍一下与表单相关的一些绑定。

(1) click绑定

语法:data-bind="click: clickHandler",这里的clickHandler函数可以是任意函数,并不一定要是ViewModel里的函数,只要能引用到即可。关于click事件有几点需要留意的:

1. 参数传递,ko默认将当前组件作为第一个参数传给clickHandler函数,这里要注意当前的绑定上下文,比如说在with环境中,传回的组件就会变成with组件而不是你想要的当前组件。如果你还需要传递event参数,则将event作为第二个参数传入。如果还需要传入更多的参数,那么就需要使用一个函数包装起来了。如:

<button data-bind="click: function(data, event) { myFunction('param1', 'param2', data, event) }">
Click me
</button>

2. 默认行为的设置(比如链接)

ko默认是禁止默认事件行为的,通常我们为链接绑定点击事件也不会是让其跳转的。不过你如果一定要开启的话,直接在clickHandler里面return true即可。

3. 冒泡

ko默认是允许冒泡的,你可以通过 data-bind="click: clickHandler, clickBubble: false"来设置click事件不冒泡。

(2)event绑定

ko提供了这个接口让用户自定义绑定事件。关于参数传递、默认行为、冒泡等与click绑定是一样的,使用案例:

<div>
<div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails }">
Mouse over me
</div>
<div data-bind="visible: detailsEnabled">
Details
</div>
</div>
<script type="text/javascript">
var viewModel = {
detailsEnabled: ko.observable(false),
enableDetails: function() {
this.detailsEnabled(true);
},
disableDetails: function() {
this.detailsEnabled(false);
}
};
ko.applyBindings(viewModel);
</script>

(3)submit绑定

主要用来做一些验证表单的工作。ko会阻止默认的提交表单动作,并转入submit绑定的函数中。后续需要提交的时候,在绑定事件中 return true即可。

PS: 为什么不在表单中使用 click 事件来处理呢?因为 submit 本来就是被设计用来处理提交事件的,它还能接受回车一类的提交动作,但click则不行。

(4)value 与 textInput 绑定

在输入框绑定 value 和 textInput 看起来效果差不多,但是更推荐使用 textInput 事件进行绑定,因为 textInput 是新增的专门用来处理输入事件的。在上一篇文章中可以看到,使用 value 绑定时(左)输入之后必须要将焦点从输入框中移出才会进行更新,而 textInput (右)是马上进行更新的。

Knockoutjs 学习系列(二)花式捆绑 Knockoutjs 学习系列(二)花式捆绑

虽然,value 绑定也可以通过设置 data-bind="{value: price, valueUpdate: 'afterkeydown'}" 实现与 textInput 一样的效果,但是这个在浏览器中的兼容性并不如 textInput 好。

(5)options绑定(selectedOptions)

在下拉列表中可使用 options 来绑定子项的值,子项既可以是字符串,也可以是 js 对象。上一篇(【Knockoutjs 学习体验之旅】(1)ko初体验)中展示的是字符串,这次就来传个对象:

代码:

<p>Your country:
<select data-bind="options: availableCountries,
optionsText: 'countryName',
value: selectedCountry,
optionsCaption: 'Choose...'"></select>
</p>
<div data-bind="visible: selectedCountry">
<!-- Appears when you select something -->
You have chosen a country with population
<span data-bind="text: selectedCountry() ? selectedCountry().countryPopulation : 'unknown'"></span>.
</div>
<script type="text/javascript">
// Constructor for an object with two properties
var Country = function(name, population) {
this.countryName = name;
this.countryPopulation = population;
};
var viewModel = {
availableCountries: ko.observableArray([
new Country("UK", 65000000),
new Country("USA", 320000000),
new Country("Sweden", 29000000)
]),
selectedCountry: ko.observable() // Nothing selected by default
};
ko.applyBindings(viewModel);
</script>

这里使用了option来绑定列表框的选项,使用value绑定选中项目。由于选项是 js 对象,所以要用一个 optionText 来指定在列表框中的展示。optionCaption是指无选中任何项目时候的默认显示值。如果我们设定的是多选列表框的话,那么就不能用 value 来绑定选中项目了,这个时候要用到 selectOptions来绑定选中项目。

(6)其他绑定:enable/disable, hasFocus , checked , uniqueName。

这些事件用起来非常简单,就不具体介绍了。最后一个 uniqueName 是用来设置表单控件的唯一 name 属性的,表单中提交到后台时,没有设置 name 属性的值时不会被提交到后台的,所以就有了这么个绑定功能。官网中关于 hasFoucus 还有个比较常用的效果:

Name:

Name: Bert Bertington

Click the name to edit it; click elsewhere to apply changes.

点击上面的姓名就可以变成可编辑状态,失去焦点后又变成普通文字,这种效果用ko实现起来相当简单。

总结

本篇主要简单介绍了knockoutjs中各种绑定的使用方法,使用这些绑定方法的组合就能简单地做好一个需要较多动态交互的UI页面。使用这些方法比较重要的一点就是要记住绑定的都是函数对象,所以可以直接在HTML里面进行操作,这样的话有时候 js 代码结构可以更简单。

官方教程: http://knockoutjs.com/documentation/introduction.html

Javascript 相关文章推荐
Extjs表单常见验证小结
Mar 07 Javascript
jQuery常用且重要方法汇总
Jul 13 Javascript
Javascript BOM学习小结(六)
Nov 26 Javascript
JS获取鼠标坐标位置实例分析
Jan 20 Javascript
javascript自定义滚动条实现代码
Apr 20 Javascript
jquery radio的取值_radio的选中_radio的重置方法
Sep 20 Javascript
jQuery自定义图片上传插件实例代码
Apr 04 jQuery
js实现分页功能
May 24 Javascript
js自定义Tab选项卡效果
Jun 05 Javascript
react.js 父子组件数据绑定实时通讯的示例代码
Sep 25 Javascript
浅谈React之状态(State)
Sep 19 Javascript
vue中的循环对象属性和属性值用法
Sep 04 Javascript
Knockoutjs 学习系列(一)ko初体验
Jun 07 #Javascript
【经典源码收藏】jQuery实用代码片段(筛选,搜索,样式,清除默认值,多选等)
Jun 07 #Javascript
Javascript之Number对象介绍
Jun 07 #Javascript
Javascript之Math对象详解
Jun 07 #Javascript
分享jQuery网页元素拖拽插件
Dec 01 #Javascript
【经典源码收藏】基于jQuery的项目常见函数封装集合
Jun 07 #Javascript
全面解析DOM操作和jQuery实现选项移动操作代码分享
Jun 07 #Javascript
You might like
解析link_mysql的php版
2013/06/30 PHP
PHP函数实现分页含文本分页和数字分页
2014/10/23 PHP
PHP中Header使用的HTTP协议及常用方法小结
2014/11/04 PHP
日常整理PHP中简单的图形处理(经典)
2015/10/26 PHP
我整理的PHP 7.0主要新特性
2016/01/07 PHP
PHP进程通信基础之信号量与共享内存通信
2017/02/19 PHP
PHP调用API接口实现天气查询功能的示例
2017/09/21 PHP
js检查页面上有无重复id的实现代码
2013/07/17 Javascript
jquery右下角弹出提示框示例代码
2013/10/08 Javascript
js拆分字符串并将分割的数据放到数组中的方法
2015/05/06 Javascript
基于JS代码实现实时显示系统时间
2016/06/16 Javascript
vue数据双向绑定原理解析(get &amp; set)
2017/03/08 Javascript
Angular.js基础学习之初始化
2017/03/10 Javascript
JS优化与惰性载入函数实例分析
2017/04/06 Javascript
node.js基础知识小结
2018/02/26 Javascript
js实现动态改变radio状态的方法
2018/02/28 Javascript
详解nodejs通过响应回写的方式渲染页面资源
2018/04/07 NodeJs
vue配置多页面的实现方法
2018/05/22 Javascript
基于VUE实现的九宫格抽奖功能
2018/09/30 Javascript
JavaScript HTML DOM 元素 (节点)新增,编辑,删除操作实例分析
2020/03/02 Javascript
解决vue2中使用elementUi打包报错的问题
2020/09/22 Javascript
python常见排序算法基础教程
2017/04/13 Python
Python+OpenCV实现图像融合的原理及代码
2018/12/03 Python
selenium+python自动化测试之页面元素定位
2019/01/23 Python
python文件读写代码实例
2019/10/21 Python
wxPython实现文本框基础组件
2019/11/18 Python
在python中利用dict转json按输入顺序输出内容方式
2020/02/27 Python
中国医药集团国药在线:国药网
2017/02/06 全球购物
韩国11街:11STREET
2018/03/27 全球购物
英国最大的自有市场,比亚马逊便宜:Flubit
2019/03/19 全球购物
屈臣氏马来西亚官网:Watsons马来西亚
2019/06/15 全球购物
AJAX应用和传统Web应用有什么不同
2013/08/24 面试题
银行实习自我鉴定
2013/10/12 职场文书
大学生求职自荐信
2013/12/12 职场文书
网上蛋糕店创业计划书
2014/01/24 职场文书
超市重阳节活动方案
2014/02/10 职场文书