AngularJS应用开发思维之2:数据绑定
在声明式模板中显示数据
因为不能像jQuery一样将DOM操作混在模板里,声明式模板很快让我们变得束手束脚。
一个典型的问题:在声明式模板里怎么显示数据?
假设我们有某人的基本信息,保存在一个json对象里:
- var sb = {
- name : 'somebody',
- gender : 'male',
- age : 28
- };
我们定义一个指令ez-namecard,希望它经过编译后会展开成这样:
- <div>
- <div>name : somebody </div>
- <div>gender : male </div>
- <div>age : 28</div>
- </div>
那么,怎么把sb这个json对象指定给ez-namecard这个指令?
将数据传递给指令
一个容易想到的方法,就是给指令ez-namecard增加一个属性,用这个属性的值 指定数据对象的变量名称。
这相当于,用属性向指令(解释器)传递参数:
- <ez-namecard data="window.sb"></ez-namecard>
这样的话,ez-namecard的解释器只要检查data属性,然后执行一个eval()就可以获得sb的值, 从而将其内容填充到展开的div片段中。
BINGO!
作用域/Scope
不过,请注意,前面定义的sb变量,默认是挂在window对象(命名空间)上的,即window.sb。 如果所有的数据都挂在window上,保不齐哪天就会出现变量的命名冲突。
AngularJS引入了一个自用的命名空间,也就是$rootScope对象,这样sb变量就可以 挂在$rootScope上了,即$rootScope.sb。
引入了scope的代码参见→_→。
在HTML模板中,我们用了两个内置指令:
- ng-app指令会在启动引导时创建一个$rootScope对象。
- ng-init指令用来在作用域上初始化变量,这个指令将在$rootScope上建立sb对象。
在指令的实现代码中,与之前使用eval函数进行表达式估值不同,我们直接使用scope的$eval方法获 得sb变量的值。
你可能注意到,这个scope是link函数传入的参数,它和我们说的$rootScope是一个东西吗?
层级的作用域
在AngularJS中,ng-app开始的DOM子树上,每个DOM对象都有一个对应的scope对象。 比如,在我们的示例中,body对象对应一个scope对象(因为body元素有ng-app属性,所以 这个scope就是$rootScope对象),ez-namecard对象也对应一个scope对象......
在默认情况下,一个DOM子元素不会创建新的作用域,也就是说,这个子元素所对应的 scope对象,其实就是它的最近一级的祖先对象对应的scope对象。比如,在我们的例子中, ez-namecard对应的scope对象,就是它的父对象即body对象的scope对象,恰好也就是 $rootScope对象;而ez-namecard有3个div子元素对应的scope对象,也是$rootScope对象。
有些指令会导致创建新的作用域,比如ng-controller。如果在一个DOM对象上创建了新 的作用域,那么这个scope对象的原型是其最近一级的组件对象的scope对象。
比如在我们的例子中,如果在ez-namecard上使用ng-controller指令,那么ez-namecard 对应的scope对象就不再是body对应的$rootScope对象,但是由于是原型继承,所以通过 这个scope依然可以访问到sb变量。
监听数据的变化
我们已经实现了将数据显示到界面上,不过这还不够。
由于编译仅仅在启动引导时执行一次,这意味着我们的link函数只会被调用一次,那么, 如果数据变化,在界面上将不会有任何反馈,即界面和数据将变得不同步了。
这需要持续监听数据的变化。
好在AngularJS的scope对象可以使用$watch()方法,对建立在其上的变量的变化进行监听:
- $watch(watchExpression, listener, [objectEquality]);
$watch方法要求传入三个参数:
- watchExpression - 要监听的表达式,比如:"sb"
- listener - 变化发生时的回调函数,AngularJS将向这个函数传入新值和旧值
- objectEquality - 如果监听表达式的值是一个对象,应当将这个参数置为true。
→_→是经过改进后的代码,当数据被改变时,界面会自动得到更新。这时,我们称,建立了从 数据到界面的单向绑定。为了验证这一点,在代码中我们追加了一个定时器自动 更新数据的age值。
你可以试着去掉监听部分代码,看有什么效果。
如何修改数据
一旦在指令的实现代码中可以访问数据模型,那么使用声明式模板实现数据 修改也非常简单了。
我们定义一个新的指令:ez-namecard-editor,意图让其展开成这样:
- <ul>
- <li>name : <input type="text"> </li>
- <li>gender : <input type="text"> </li>
- <li>age : <input type="text"></li>
- </ul>
在ez-namecard-editor的指令实现中,为了用input中的值自动更新 sb变量中的值,我们需要在给input对象挂接上监听函数(示例中使用keyup事件), 在监听函数中实现对sb变量的修改。
最终的效果是,用户在界面上进行的操作,自动地同步到了我们的数据。这时,我们称, 已经建立了从界面到数据的单向绑定。
→_→的示例代码中,为了验证绑定的效果,我们增加了一个ez-logger指令。这个指令 将一个DOM元素的内容绑定到指定的变量上。
这样,当我们通过ez-namecard-editor修改数据时,可以同步地看到变化后的内容。
AngularJS应用开发思维之2:数据绑定的更多相关文章
- AngularJS应用开发思维之3:依赖注入
找不到的API? AngularJS提供了一些功能的封装,但是当你试图通过全局对象angular去 访问这些功能时,却发现与以往遇到的库大不相同. $http 比如,在jQuery中,我们知道它的AP ...
- AngularJS应用开发思维之1:声明式界面
这篇博客之前承接上一篇:http://www.cnblogs.com/xuema/p/4335180.html 重写示例:模板.指令和视图 AngularJS最显著的特点是用静态的HTML文档,就可以 ...
- 对照jQuery和AngularJS的不同思维模
对照jQuery和AngularJS的不同思维模 Question 如果我已经熟悉了怎样使用jQuery来开发client应用.我如今打算使用AngularJS.请描写叙述一下有那些思维模式方面的东西 ...
- AngularJS入门心得2——何为双向数据绑定
前言:谁说Test工作比较轻松,最近在熟悉几个case,差点没疯.最近又是断断续续的看我的AngularJS,总觉得自己还是没有入门,可能是自己欠前端的东西太多了,看不了几行代码就有几个常用函数不熟悉 ...
- 《Node.js+MongoDB+AngularJS Web开发》读书笔记及联想
总体介绍 <Node.js+MongoDB+AngularJS Web开发>,于2015年6月出版,是一本翻译过来的书,原书名为<Node.js,MongoDB and Angula ...
- 《微信小程序七日谈》- 第二天:你可能要抛弃原来的响应式开发思维
<微信小程序七日谈>系列文章: 第一天:人生若只如初见: 第二天:你可能要抛弃原来的响应式开发思维: 第三天:玩转Page组件的生命周期: 第四天:页面路径最多五层?导航可以这么玩 上篇文 ...
- AngularJS 1.3中的一次性数据绑定(one-time bindings)
点击查看AngularJS系列目录 谈谈AngularJS 1.3中的一次性数据绑定(one-time bindings) 不久之前,AngularJS 1.3版本正式发布,其中添加了很多的性特性,同 ...
- AngularJS进阶(三十六)AngularJS项目开发技巧之利用Service&Promise&Resolve解决图片预加载问题(后记)
AngularJS项目开发技巧之利用Service&Promise&Resolve解决图片预加载问题(后记) 前言 在"AngularJS项目开发技巧之图片预加载" ...
- AngularJS进阶(三十一)AngularJS项目开发技巧之获取模态对话框中的组件ID
AngularJS项目开发技巧之获取模态对话框中的组件ID 需求 出于项目开发需求,需要实现的业务逻辑是:药店端点击查看"已发货""已收货"订单详情时,模块弹出 ...
随机推荐
- 【原创】构建高性能ASP.NET站点之二 优化HTTP请求(前端)
原文:[原创]构建高性能ASP.NET站点之二 优化HTTP请求(前端) 构建高性能ASP.NET站点之二 优化HTTP请求(前端) 前言: 这段时间比较的忙,文章写不是很勤,希望大家谅解. 上一篇文 ...
- 拆除vs发展c++程序开发过程中产生的.ipch和.sdf文件的方法
正在使用Visual Studio 2010发展C++当程序,你会发现,有创建一些奇怪的文件.一个叫ipch的目录,和一个与project同名的.sdf文件.并且ipch以下的文件和.sdf文件都非常 ...
- 超过lua上帝的语言
上帝的语言(god)它是基于lua和RPP新一代编程语言 为什么需要它? 1.好多人不喜欢lua语法,god的语法更像C 2.god支持元编程.闭包.协程 3.凡是lua支持的特性god也支持,lua ...
- 基于Gsoap 的ONVIF C++ 库
https://github.com/xsmart/onvifcpplib 该库支持ProfileS 和ProfileG,目前正在开发哪些,现拥有支持Event 下面是一个client样本 int _ ...
- MyBatis与Spring设置callSettersOnNulls
项目中集成Mybatis与Spring,使用的是Mybatis3.2.7,以及Spring4.0.5,mybatis-spring-1.2.2;由于项目组成员想要偷懒,将数据从DB中查询出来时须要将字 ...
- 设计管理员表;webservice用于网络安全的高端内提供服务的
admin表设计.你应该有角色表,管理员属于一个样的作用,另一个接口选项,以查看表.角色有更多的选择的能力. 角色和选项代表了许多关系,因此,我们必须保持这种关系有一个表 版权声明:本文博客原创文章, ...
- C++几个小函数
之前看书,遇到几个编程题,要实现一些库自带的函数.于是动手写了写,并且做了一些测试.今晚在测试的时候,还发现了一些其他内存分配的问题,顺路一起记下.这里只写了字符串转整型,字符串赋值函数. #incl ...
- 【CTO辩论】移动创业大军:谁斗争or变更代理
众创时代.英雄辈出. 但千军万马过独木桥,竞争厮杀也异常残酷.有人说,这个时代不宜创业,由于技术门槛高了.推广难度高了.盈利模式没了.创业变重了.玩法变了...... 也有人说,时势造英雄.天时地利人 ...
- Azure File Service in IIS
微软Azure的Storage套件中提供了新的服务File Service,让我们运行在Azure中的程序都能共享存储,一个存储账号共享的没有上线,但每个共享的上限是5G.由于File Service ...
- Grunt 之 Connect
前端开发 Grunt 之 Connect 在前端开发过程中,我们需要在开发过程中,将开发中的站点部署到服务器上,然后,在浏览器中查看实际的效果,在 Grunt 环境下,可以直接使用集成在 Grunt ...