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

在上一篇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 

效果是这样的:

上一篇文章里面也说过,XXOO里面除了传单个的属性,也可以传JSON对象,也就是说可以组合绑定属性,比如说:

<!--HTML code-->
<div data-bind="{visible: shouldShowMessage, text: myMessage, css: { profitWarning: currentProfit() < 0 }}">
You will see this message only when "shouldShowMessage" holds a true value.
</div> 

效果当然是这样的:

表现类的设置比较简单,要注意的一点就是:很多表现类的属性并不需要动态变化,这个时候可以利用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放到和模板绑定一起介绍。

看看代码:

<!--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 (右)是马上进行更新的。

虽然,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

(0)

相关推荐

  • Knockoutjs 学习系列(一)ko初体验

    MVVM框架中Angular是好,但这么大而全的框架,学习难度可不低呢,上手起码也得要个一两周吧.而knockoutjs专注于数据绑定,只需一两天就可以投入使用了,学习成本不要太低!在前端进化如此迅速的时代,学习成本也是不得不考虑的一个因素.很多时候其实我们的项目并没那么复杂,也并不需要万能的框架,更需要的反而是简单顺手的工具. Before Knockoutjs 假设我们做一个订单系统,需要显示商品单价,然后可以根据输入数量计算出总价并显示出来.使用原生代码也很容易实现,效果: 代码如下: <

  • WebApi+Bootstrap+KnockoutJs打造单页面程序

    一.前言 在前一个专题快速介绍了KnockoutJs相关知识点,也写了一些简单例子,希望通过这些例子大家可以快速入门KnockoutJs.为了让大家可以清楚地看到KnockoutJs在实际项目中的应用,本专题将介绍如何使用WebApi+Bootstrap+KnockoutJs+Asp.net MVC来打造一个单页面Web程序.这种模式也是现在大多数公司实际项目中用到的. 二.SPA(单页面)好处 在介绍具体的实现之前,我觉得有必要详细介绍了SPA.SPA,即Single Page Web App

  • KnockoutJs快速入门教程

    一.引言 之前这个系列文章已经介绍Bootstrap,详情请查看本文: <Bootstrap入门教程> ,由于最近项目中,前端是Asp.net MVC + KnockoutJs + Bootstrap来做的.所以我又重新开始写这个系列.今天就让我们来看看Web前端的MVVM框架--KnockoutJs. 二.KnockoutJs是什么? 做.NET开发的人应该都知道,WPF中就集成了MVVM框架,所以KnockoutJs也是针对Web开发的MVVM框架.关于MVVM好处简单点来说就是--使得业

  • Bootstrap与KnockoutJs相结合实现分页效果实例详解

    KnockoutJS是一个JavaScript实现的MVVM框架.非常棒.比如列表数据项增减后,不需要重新刷新整个控件片段或自己写JS增删节点,只要预先定义模板和符合其语法定义的属性即可.简单的说,我们只需要关注数据的存取. 一.引言 由于最近公司的系统需要改版,改版的新系统我打算使用KnockoutJs来制作Web前端.在做的过程中,遇到一个问题--如何使用KnockoutJs来完成分页的功能.在前一篇文章中并没有介绍使用KnockoutJs来实现分页,所以在这篇文章中,将补充用Knockou

  • BootstrapTable与KnockoutJS相结合实现增删改查功能【二】

    在上篇文章给大家介绍了BootstrapTable与KnockoutJS相结合实现增删改查功能[一],介绍了下knockout.js的一些基础用法.接下来通过本文继续给大家介绍.如果你也打算用ko去做项目,且看看吧! Bootstrap是一个前端框架,解放Web开发者的好东东,展现出的UI非常高端大气上档次,理论上可以不用写一行css.只要在标签中加上合适的属性即可. KnockoutJS是一个JavaScript实现的MVVM框架.非常棒.比如列表数据项增减后,不需要重新刷新整个控件片段或自己

  • Knockoutjs快速入门(经典)

    Knockoutjs是一个JavaScript实现的MVVM框架.主要有如下几个功能: 1. Declarative bindings 2. Observables and dependency tracking 3. Templating 它对于分离前台的业务逻辑和视图简化数据绑定过程有显著的作用.闲言少叙,直接看例子,如何下载也不说了,如果用VS开发的话用Nuget就可以一键搞定. 1.基本绑定和依赖跟踪 首先需要定义一个ViewModel: 复制代码 代码如下: <script type=

  • BootstrapTable与KnockoutJS相结合实现增删改查功能【一】

    Bootstrap是一个前端框架,解放Web开发者的好东东,展现出的UI非常高端大气上档次,理论上可以不用写一行css.只要在标签中加上合适的属性即可. KnockoutJS是一个JavaScript实现的MVVM框架.非常棒.比如列表数据项增减后,不需要重新刷新整个控件片段或自己写JS增删节点,只要预先定义模板和符合其语法定义的属性即可.简单的说,我们只需要关注数据的存取. 一.Knockout.js简介 1.Knockout.js和MVVM 如今,各种前端框架应接不暇,令人眼花缭乱,有时不得

  • knockoutjs动态加载外部的file作为component中的template数据源的实现方法

    玩过knockoutjs的都知道,有一个强大的功能叫做component,而这个component有个牛逼的地方就是拥有自己的viewmodel和template,比如下面这样: ko.components.register('message-editor', { viewModel: function(){}, template:"" }); 很显然,viewmodel就是function函数区,而template就是模板区,然后通过register函数将component注册到kn

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

    在上一篇Knockoutjs 学习系列(一)ko初体验文章中提到,ko中的 data-bind = "XX:OO"绑定大法除了可以绑定text.value等内容,还可以绑定visible.style等外观属性,也可以绑定click.textInput等各种事件,甚至还能控制程序流程.各种花式捆绑,绝对满足你的幻想. 下面简单讲讲各种绑定的使用,主要根据被绑定的属性分成表现类.流程类和交互类三种. 表现类属性 表现类的绑定属性有visible.text.html.css.style.at

  • Android开发系列二之窗口Activity的生命周期

    在上篇文章给大家介绍了android开发系列一之用按钮实现显示时间,感兴趣的朋友可以点击阅读详情. 在Activity从创建到销毁的过程中需要在不同的阶段调用7个生命周期的方法这7个生命周期方法定义如下: protected void onCreate(Bundle savedInstanceState) protected void onStart() protected void onResume() protected void onPause() protected void onSto

  • C# Redis学习系列(一)Redis下载安装使用

    下一篇:C# Redis学习系列二:Redis基本设置 一.认识Redis 1. Redis 是一个高性能的key-value数据库. 2. 它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set --有序集合)和hash(哈希类型). 3.周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件 4.别人说的 比我好 Redis百度百科 二.下载 为了匹配我的教程,我推荐下载 redis-2.8.2400 三.如何安

  • C# Redis学习系列(二)Redis基本设置

    上一篇:C# Redis学习系列一:Redis的认识.下载.安装.使用 一.redis 设置密码 使用下载好的 redis-cli.exe 指令: 1.设置密码:config set requirepass 123456 2.查看:info(验证无法通过) 3.授权登陆 auth 123456 二.Redis 更改端口(如从 6379 改到 6820) 1.打开下图:redis.conf 2.将 6379 替代为 6820 保存 3.如何开启?直接打开 redis-server.exe 你会发现

  • JAVA/JSP学习系列之八(改写MySQL翻页例子)

    一.前言 其实,改写后的JDBC Data-Source是运行在Servlet中的,通过JNDI去查找数据源.我用Orion试的,将本站<JAVA/JSP学习系列之六(MySQL翻页例子) > 简单改写了一下. 二.配置 (1)JDBC 需要将用到的JDBC驱动Copy到[ORION]/lib目录下 (2)data-source 在[ORION]/config/data-sources.xml文件中加入如下: 〈data-source class="com.evermind.sql.

  • JAVA/JSP学习系列之六(MySQL翻页例子)

    一.运行前准备 下载了mysql的jdbc驱动(一个jar文件)并加载在CLASSPATH(方法见<JAVA/JSP学习系列之一(JDK安装) >) (如果找不到,请从本站下载) 建一个MySQL数据库test 数据库中有一个表:note,字段为:name(varchar) 二.下载,安装 <%@ page contentType="text/html;charset=gb2312" %> <% java.sql.Connection sqlCon; //

  • JAVA/JSP学习系列之六

    一.运行前准备 下载了mysql的jdbc驱动(一个jar文件)并加载在CLASSPATH(方法见<JAVA/JSP学习系列之一(JDK安装) >) (如果找不到,请从本站下载) 建一个MySQL数据库test 数据库中有一个表:note,字段为:name(varchar) 二.下载,安装 intPageCount) intPage = intPageCount; %> 姓名 0) { //将记录指针定位到待显示页的第一条记录上 sqlRst.absolute((intPage-1) *

  • rabbitmq学习系列教程之消息应答(autoAck)、队列持久化(durable)及消息持久化

    目录 一.前言 二.autoAck参数的讨论 三.rabbitmq队列持久化操作 四.2019.11.04问题补充 五.2019.11.07消息的持久化 六.2022.02.09增加队列持久化说明 结语 一.前言 Boolean autoAck = false; channel.basicConsume(queue_name, autoAck ,consumer); 在simple queue 和 work queue(轮询) 处理中,我们设置的消费者的消息监听都采用 channel.basic

  • BootStrap学习系列之Bootstrap Typeahead 组件实现百度下拉效果(续)

    接着上篇的内容,在上篇给大家介绍了Bootstrap学习系列之使用 Bootstrap Typeahead 组件实现百度下拉效果 Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷. 官方:http://twitter.github.io/typeahead.js/ 示例:http://twitter.github.io/typeahead.js/examples/(本

随机推荐