详解JavaScript的AngularJS框架中的作用域与数据绑定_

上传人:一** 文档编号:26323197 上传时间:2021-08-08 格式:DOCX 页数:18 大小:18.25KB
返回 下载 相关 举报
详解JavaScript的AngularJS框架中的作用域与数据绑定__第1页
第1页 / 共18页
详解JavaScript的AngularJS框架中的作用域与数据绑定__第2页
第2页 / 共18页
详解JavaScript的AngularJS框架中的作用域与数据绑定__第3页
第3页 / 共18页
点击查看更多>>
资源描述
详解JavaScript的AngularJS框架中的作用域与数据绑定_ AngularJS 简介 AngularJS 是由 Google 发起的一款开源的前端 MVC 脚本框架,既适合做一般 WEB 应用也可以做 SPA(单页面应用,全部的用户操作都在一个页面中完成)。与同为 MVC 框架的 Dojo 的定位不同,AngularJS 在功能上更加轻量,而相比于 jQuery,AngularJS 又帮您省去了很多机械的绑定工作。在一些对开发速度要求高,功能模块不需要太丰富的非企业级 WEB 应用上,AngularJS 是一个特别好的选择。AngularJS 最为简单同时也是最强大的部分就是它的数据绑定机制,这个机制关心我们能更好的将留意力集中在数据的模型建立和传递上,而不是对底层的 DOM 进行低级的操作。 AngularJS 作用域 基于 jQuery 的传统 WEB 应用中,为了监听用户的输入等行为,需要为每一个 DOM 元素设置一个监听方法,也即是监听 DOM 上发生的各类大事,然后由 jQuery 做出回应并展现在页面上。这种方法简便直观,但是一旦 WEB 应用变得浩大而且简单,那么监听代码就显得特别的机械而且冗余,更可怕的是,假如对于 DOM 的大事监听没有做好管理,那么很简单消失扫瞄器资源的泄露。 针对以上所暴露的问题,AngularJS 用一系列指令来代替 jQuery 的大事绑定代码。为了能够组织好各类指令之间的协调工作而不消失数据混乱,AngularJS 在模型层上引申出作用域的概念,以配合掌握器来实现对视图层的呈现工作。 作用域(Scope) AngularJS 中,作用域是一个指向应用模型的对象,它是表达式的执行环境。作用域有层次结构,这个层次和相应的 DOM 几乎是一样的。作用域能监控表达式和传递大事。 在 HTML 代码中,一旦一个 ng-app 指令被定义,那么一个作用域就产生了,由 ng-app 所生成的作用域比较特别,它是一个根作用域($rootScope),它是其他全部$Scope 的最顶层。 清单 1. 生成根作用域 html headscript src=angular.min.js/script/head body data-ng-app=app./body /html 除了用 ng-app 指令可以产生一个作用域之外,其他的指令如 ng-controller,ng-repeat 等都会产生一个或者多个作用域。此外,还可以通过 AngularJS 供应的创建作用域的工厂方法来创建一个作用域。这些作用域都拥有自己的继承上下文,并且根作用域都为$rootScope。 在生成一个作用域之后,在编写 AngularJS 代码时,$scope 对象就代表了这个作用域的数据实体,我们可以在$scope 内定义各种数据类型,之后可以挺直在 HTML 中以 变量名 方式来让 HTML 访问到这个变量,代码如下: 清单 2. 简洁的数据绑定 script angular.module(app, ) .controller(ctrl, function ($scope) $scope.btns = ibm : ibm ; ); /script /head body data-ng-app=app div data-ng-controller=ctrl buttonbtns.ibm/button /div /body 这就是 AngularJS 中最简洁的数据绑定方式,同时也是应用最为广泛的数据绑定方式。 继承作用域(Inherited Scope) AngularJS 在创建一个作用域时,会检索上下文,假如上下文中已经存在一个作用域,那么这个新创建的作用域就会以 JavaScript 原型继承机制继承其父作用域的属性和方法(有个例外是孤立作用域,下文商量)。 一些 AngularJS 指令会创建新的子作用域,并且进行原型继承: ng-repeat、ng-include、ng-switch、ng-view、ng-controller, 用 scope: true 和 transclude: true 创建的 directive。 以下 HTML 中定义了三个作用域,分别是由 ng-app 指令所创建的$rootScope,parentCtrl 和 childCtrl 所创建的子作用域,这其中 childCtrl 生成的作用域又是 parentCtrl 的子作用域。 清单 3. 作用域的继承实例 body data-ng-app=app div data-ng-controller=parentCtrl input data-ng-model=args div data-ng-controller=childCtrl input data-ng-model=args /div /div /body 继承作用域符合 JavaScript 的原型继承机制,这意味着假如我们在子作用域中访问一个父作用域中定义的属性,JavaScript 首先在子作用域中查找该属性,没找到再从原型链上的父作用域中查找,假如还没找到会再往上一级原型链的父作用域查找。在 AngularJS 中,作用域原型链的顶端是$rootScope,AnguarJS 将会查找到$rootScope 为止,假如还是找不到,则会返回 undefined。 我们用实例代码说明下这个机制。首先,我们探讨下对于原型数据类型的作用域继承机制: 清单 4. 作用域继承实例-原始类型数据继承 script type=text/javascript angular.module(app, ) .controller(parentCtrl, $scope, function($scope) $scope.args = IBM DeveloperWorks; ) .controller(childCtrl, $scope, function($scope) ); /script body data-ng-app=app div data-ng-controller=parentCtrl input data-ng-model=args div data-ng-controller=childCtrl input data-ng-model=args /div /div /body 运行页面,我们得到以下的结果: 图 1. 页面运行结果。 这个结果我们特别好理解,虽然在 childCtrl 中没有定义具体的 args 属性,但是由于 childCtrl 的作用域继承自 parentCtrl 的作用域,因此,AngularJS 会找到父作用域中的 args 属性并设置到输入框中。而且,假如我们在第一个输入框中转变内容,内容将会同步的反应到其次个输入框: 图 2. 转变第一个输入框的内容后页面运行结果 假如我们修改其次个输入框的内容,此时会发生什么事情呢?答案是其次个输入框的内容从今将不再和第一个输入框的内容保持同步。在转变其次个输入框的内容时,由于 HTML 代码中 model 明确绑定在 childCtrl 的作用域中,因此 AngularJS 会为 childCtrl 生成一个 args 原始类型属性。这样,依据 AngularJS 作用域继承原型机制,childCtrl 在自己的作用域找得到 args 这个属性,从而也不再会去查找 parentCtrl 的 args 属性。从今,两个输入框的内容所绑定的属性已经是两份不同的实例,因此不会再保持同步。 图 3. 转变其次个输入框的内容后页面运行结果 假如我们将代码做如下修改,结合以上两个场景,思索下会消失怎样的结果? 清单 5. 作用域继承实例-对象数据继承 script type=text/javascript angular.module(app, ) .controller(parentCtrl, $scope, function($scope) $scope.args = ; $scope.args.content = IBM DeveloperWorks; ) .controller(childCtrl, $scope, function($scope) ); /script body data-ng-app=app div data-ng-controller=parentCtrl input data-ng-model=args.content div data-ng-controller=childCtrl input data-ng-model=args.content /div /div /body 答案是无论转变任何一个输入框的内容,两者的内容始终同步。 依据 AngularJS 的原型继承机制,假如 ng-model 绑定的是一个对象数据,那么 AngularJS 将不会为 childCtrl 创建一个 args 的对象,自然也不会有 args.content 属性。这样,childCtrl 作用域中将始终不会存在 args.content 属性,只能从父作用域中查找,也即是两个输入框的的改变其实只是在转变 parentCtrl 作用域中的 args.content 属性。因此,两者的内容始终保持同步。 我们再看一个例子,这次请读者自行分析结果。 清单 6. 作用域继承实例-不再访问父作用域的数据对象。 script type=text/javascript angular.module(app, ) .controller(parentCtrl, $scope, function($scope) $scope.args = ; $scope.args.content = IBM DeveloperWorks; ) .controller(childCtrl, $scope, function($scope) $scope.args = ; $scope.args.content = IBM DeveloperWorks; ); /script body data-ng-app=app div data-ng-controller=parentCtrl input data-ng-model=args.content div data-ng-controller=childCtrl input data-ng-model=args.content /div /div /body 答案是两个输入框的内容永久不会同步。 孤立作用域(Isolate Scope) 孤立作用域是 AngularJS 中一个特别特别的作用域,它只在 directive 中消失。在对 directive 的定义中,我们添加上一个 scope: 属性,就为这个 directive 创建出了一个隔离作用域。 清单 7. directive 创建出一个孤立作用域 angular.module(isolate, ).directive(isolate, function () return scope : , ; ) 孤立作用域最大的特点是不会原型继承其父作用域,对外界的父作用域保持相对的独立。因此,假如在定义了孤立作用域的 AngularJS directive 中想要访问其父作用域的属性,则得到的值为 undefined。代码如下: 清单 8. 孤立作用域的隔离性 script type=text/javascript angular.module(app, ) .controller(ctrl, $scope, function($scope) $scope.args = ; ) .directive(isolateDirective, function () return scope : , link : function($scope, $element, $attr) console.log($scope.$args); /输出 undefined ; ); /script body data-ng-app=app div data-ng-controller=ctrl div data-isolate-directive/div /div /body 上面的代码中通过在 directive 中声明白 scope 属性从而创建了一个作用域,其父作用域为 ctrl 所属的作用域。但是,这个作用域是孤立的,因此,它访问不到父作用域的中的任何属性。存在这样设计机制的好处是:能够创建出一些列可复用的 directive,这些 directive 不会相互在拥有的属性值上产生串扰,也不会产生任何副作用。 AngularJS 孤立作用域的数据绑定 在继承作用域中,我们可以选择子作用域挺直操作父作用域数据来实现父子作用域的通信,而在孤立作用域中,子作用域不能挺直访问和修改父作用域的属性和值。为了能够使孤立作用域也能和外界通信,AngularJS 供应了三种方式用来打破孤立作用域“孤立”这一限制。 单向绑定( 或者 attr) 这是 AngularJS 孤立作用域与外界父作用域进行数据通信中最简洁的一种,绑定的对象只能是父作用域中的字符串值,并且为单向只读引用,无法对父作用域中的字符串值进行修改,此外,这个字符串还必需在父作用域的 HTML 节点中以 attr(属性)的方式声明。 用法这种绑定方式时,需要在 directive 的 scope 属性中明确指定引用父作用域中的 HTML 字符串属性,否则会抛特别。示例代码如下: 清单 9. 单向绑定示例 script angular.module(isolateScope, ) .directive(isolateDirective, function () return replace : true, template: buttonisolates/button, scope : isolates : , , link : function($scope, $element, $attr) $scope.isolates = DeveloperWorks; ; ) .controller(ctrl, function ($scope) $scope.btns = IBM; ); /script body data-ng-app=isolateScope div data-ng-controller=ctrl buttonbtns/button div data-isolate-directive data-isolates=btns/div /div /body 简洁分析下上面的代码,通过在 directive 中声明白 scope:isolates: 使得 directive 拥有了父作用域中 data-isolates 这个 HTML 属性所拥有的值,这个值在掌握器 ctrl 中被赋值为IBM。所以,代码的运行结果是页面上有两个名为 IBM 的按钮。 我们还留意到 link 函数中对 isolates 进行了修改,但是最终不会在运行结果中体现。这是由于 isolates 始终绑定为父作用域中的 btns 字符串,假如父作用域中的 btns 不转变,那么在孤立作用域中无论怎么修改 isolates 都不会起作用。 引用绑定(或者attr) 通过这种形式的绑定,孤立作用域将有力量访问到父作用域中的函数对象,从而能够执行父作用域中的函数来猎取某些结果。这种方式的绑定跟单向绑定一样,只能以只读的方式访问父作用函数,并且这个函数的定义必需写在父作用域 HTML 中的 attr(属性)节点上。 这种方式的绑定虽然无法修改父作用域的 attr 所设定的函数对象,但是却可以通过执行函数来转变父作用域中某些属性的值,来达到一些预期的效果。示例代码如下: 清单 10. 引用绑定示例 script angular.module(isolateScope, ) .directive(isolateDirective, function () return replace : true, scope : isolates : , , link : function($scope, $element, $attr) var func = $scope.isolates(); func(); ; ) .controller(ctrl, function ($scope) $scope.func = function () console.log(IBM DeveloperWorks); ); /script body data-ng-app=isolateScope div data-ng-controller=ctrl div data-isolate-directive data-isolates=func/div /div /body 这个例子中,扫瞄器的掌握台将会输出一段“IBM DeveloperWorks”文字。 上面的代码中我们在父作用域中指定了一个函数对象$scope.func,在孤立作用域中通过对 HTML 属性的绑定从而引用了 func。需要留意的是 link 函数中对 func 对象的用法方法,$scope.isolates 获得的仅仅是函数对象,而不是调用这个对象,因此我们需要在调用完$scope.isolates 之后再调用这个函数,才能得到真正的执行结果。 双向绑定(=或者=attr) 双向绑定给予 AngularJS 孤立作用域与外界最为自由的双向数据通信功能。在双向绑定模式下,孤立作用域能够挺直读写父作用域中的属性和数据。和以上两种孤立作用域定义数据绑定一样,双向绑定也必需在父作用域的 HTML 中设定属性节点来绑定。 双向绑定特别适用于一些子 directive 需要频繁和父作用域进行数据交互,并且数据比较简单的场景。不过,由于可以自由的读写父作用域中的属性和对象,所以在一些多个 directive 共享父作用域数据的场景下需要当心用法,很简单引起数据上的混乱。 示例代码如下: 清单 11. 双向绑定示例 script angular.module(isolateScope, ) .directive(isolateDirective, function () return replace : true, template: buttonisolates/button, scope : isolates : =, , link : function($scope, $element, $attr) $scope.isolates.ibm = IBM; ; ) .controller(ctrl, function ($scope) $scope.btns = ibm : ibm, dw : DeveloperWorks ; ); /script body data-ng-app=isolateScope div data-ng-controller=ctrl buttonbtns.dw/button buttonbtns.ibm/button div data-isolate-directive data-isolates=btns/div /div /body 上面的代码运行的结果是扫瞄器页面上消失三个按钮,其中第一个按钮标题为“DeveloperWorks”,其次和第三个按钮的标题为“IBM”。 初始时父作用域中的$scope.btns.ibm 为小写的“ibm”,通过双向绑定,孤立作用域中将父作用域的 ibm 改写成为大写的“IBM”并且挺直生效,父作用域的值被更改。 总结 由于 AngularJS 框架的轻量性和其清楚的 MVC 特点使得其在推出之后就大受欢迎,实践中也很简单上手。AngularJS 比较难以把握和理解的就是其作用域和绑定机制,本文重点将作用域和绑定机制做了分析与商量,盼望读者能够理解并娴熟把握这块内容。 .
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 工作计划


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!