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 相关文章推荐
Javascript MD4
Dec 20 Javascript
Javascript限制网页只能在微信内置浏览器中访问
Nov 09 Javascript
深入解读JavaScript中的Hoisting机制
Aug 12 Javascript
实例讲解javascript注册事件处理函数
Jan 09 Javascript
connection reset by peer问题总结及解决方案
Oct 21 Javascript
浅谈JS对html标签的属性的干预以及对CSS样式表属性的干预
Jun 25 Javascript
用vue构建多页面应用的示例代码
Sep 20 Javascript
vue-router启用history模式下的开发及非根目录部署方法
Dec 23 Javascript
Vue2(三)实现子菜单展开收缩,带动画效果实现方法
Apr 28 Javascript
js实现盒子滚动动画效果
Aug 09 Javascript
JS实现简易贪吃蛇游戏
Aug 24 Javascript
使用react-virtualized实现图片动态高度长列表的问题
May 28 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
PHP图片处理之使用imagecopyresampled函数裁剪图片例子
2014/11/19 PHP
php构造函数与析构函数
2016/04/23 PHP
JavaScript 私有成员分析
2009/01/13 Javascript
原生Js实现按的数据源均分时间点幻灯片效果(已封装)
2010/12/28 Javascript
JS分页控件 可用于无刷新分页
2013/07/23 Javascript
jQuery过滤选择器:not()方法使用介绍
2014/04/20 Javascript
JavaScript Sort 的一个错误用法示例
2015/03/20 Javascript
JavaScript中的普通函数与构造函数比较
2015/04/07 Javascript
详解JavaScript中Date.UTC()方法的使用
2015/06/12 Javascript
JavaScript实现向右伸出的多级网页菜单效果
2015/08/25 Javascript
Bootstrap Table使用方法详解
2016/08/01 Javascript
Vue.js组件tab实现选项卡切换
2020/03/23 Javascript
ajax请求data遇到的问题分析
2018/01/18 Javascript
解决VUE中document.body.scrollTop为0的问题
2018/09/15 Javascript
Jquery的autocomplete插件用法及参数讲解
2019/03/12 jQuery
node实现简单的增删改查接口实例代码
2019/08/22 Javascript
iSlider手机端图片滑动切换插件使用详解
2019/12/24 Javascript
vue实现导航菜单和编辑文本的示例代码
2020/07/04 Javascript
VUE使用 wx-open-launch-app 组件开发微信打开APP功能
2020/08/11 Javascript
Vue-cli assets SubDirectory及PublicPath区别详解
2020/08/18 Javascript
全面解析Vue中的$nextTick
2020/12/24 Vue.js
[55:18]Liquid vs Chaos 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
[40:03]RNG vs VG 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
Python运维自动化之nginx配置文件对比操作示例
2018/08/29 Python
Python基础之循环语句用法示例【for、while循环】
2019/03/23 Python
python算法与数据结构之单链表的实现代码
2019/06/27 Python
浅谈python多进程共享变量Value的使用tips
2019/07/16 Python
pytorch载入预训练模型后,实现训练指定层
2020/01/06 Python
对python中arange()和linspace()的区别说明
2020/05/03 Python
整个世界的设计师家具在哈恩:Designathome
2019/03/25 全球购物
自我鉴定写作要点
2014/01/17 职场文书
计算机求职自荐信范文
2014/04/19 职场文书
师范大学生求职信
2014/06/13 职场文书
学生会竞选演讲稿怎么写
2014/08/26 职场文书
工程进度款催款函
2015/06/24 职场文书
Java基础之线程锁相关知识总结
2021/06/30 Java/Android