学习Angular中作用域需要注意的坑

 更新时间:2016年8月24日 10:00  点击:2204

Angular作用域

在用angular搭建的网页应用中,作用域(scope)这个概念是贯穿其中的。在angular的视图(view)中的很多指令是会创建一个作用域的,例如 ng-app , ng-controller 等。这个作用域就是我们在写控制器构造函数时注入的 $scope (angular1.2之前的版本),他是视图模型(view model)中的一个概念。我们的数据模型(model)就是定义在作用域中的。

Angular作用域的坑

用过angular的人应该都会经过一个过程,就是刚开始还是小白的时候,刚看见数据双向绑定觉得很牛逼,

Angular中作用域的坑1

管他三七二十一直接开始用,一顿绑定。绑定完之后,如果你运气好(懂得angular作用域原理的老鸟无视),那么双向绑定就开始如愿工作了,这时候我们也觉得自己好厉害,居然可以这么快就实现“双向绑定”这个才听说不久的新功能了。

那么为什么上面说双向绑定是因为运气好才能正常工作呢?因为新手刚开始学angular的时候,无非就是看教程然后改动其中的代码实现自己的业务需求,能刚开始就去学习官方文档的选手就算有也是少数,所以这样,大多数刚学习angular的朋友实际上不太了解其中的原理,但是觉得自己已经会用了。

好说了这么多,那我们来看看如果一个新手刚开始给作用域中指定数据模型并且进行双向绑定时,运气不那么好的情况。这种情况下,就会遇到上面说的坑,先来看看代码

// html
<div ng-controller="OuterCtrl">
  <span ng-bind="a"></span>
  <div ng-controller="InnerCtrl">
    <span ng-bind="a"></span>
    <button ng-click="a=a+1">递增</button>
  </div>
</div>

// javascript
function OuterCtrl($scope) {
  $scope.a = 1;
}
function InnerCtrl() {}

上面的代码就是一个极其简单的双向绑定的例子。页面加载以后,外部 div 和内部 div 中都会显示1。当按了递增按钮之后,会发现只有内部的1变成了2,继续按也是一样,只有内部的数字会递增。那么这时候,新手往往就慌了,说好的神奇的双向绑定呢?

Angular中作用域的坑2

这个时候宝宝就有点小情绪了,stackoverflow走起,官方文档走起,最后发现确实有解决方法,比如说将 a 写成一个对象的属性 data.a

// html
<div ng-controller="OuterCtrl">
  <span ng-bind="data.a"></span>
  <div ng-controller="InnerCtrl">
    <span ng-bind="data.a"></span>
    <button ng-click="data.a=data.a+1">递增</button>
  </div>
</div>

// javascript
function OuterCtrl($scope) {
  $scope.data = {
    a: 1
  };
}
function InnerCtrl() {}

然后发现,居然可以工作了,两个数字都跟着递增了,我是双向绑定之王……然后就扔一边也不管具体的原理继续学习下一部分教程了。这其实就是我当初学习angular的心路历程,实在惭愧做了应用部署到生产环境之后才想起来去研究研究内部的原理。

坑总是要填的

废话说了那么多,坑也去踩了,下面进入填坑阶段,也就是这个坑是为什么会出现为什么写成对象的属性就能解决。其实知道了原理之后,是很容易理解的。angular的内外层作用域之间是基于javascript的原型链来实现的继承,并且只使用了原型链继承方法,有点JavaScript基础的朋友应该就能瞬间反应过来,子类原型对象中的引用类型值和父类实例对象中的引用类型值是引用的同一个,而基本类型值则会覆盖父类对象中的基本类型值,这其实也是组合继承存在的原因,因为光用原型链继承会带来上诉问题,扯得有点远

总之这里,我们可以这样来看待第一个例子:

function OuterCtrl() {
  this.a = 1;
}
function InnerCtrl() {}

var outer = new OuterCtrl();
InnerCtrl.prototype = outer;
var inner = new InnerCtrl();
inner.a = inner.a + 1;

这里,我们将内部的控制器的构造函数的原型对象设置为外部作用域对象,这样产生的内部作用域对象就继承了外部对象 outer 中的属性 a 。这个属性是个基本类型值,对内部对象的属性 a 进行访问的时候,由于内部对象本身不存在这样的属性,就会从它的原型对象中查找,原型对象 outer 中存在这样的属性,于是返回值,没有问题,但是如果我们对内部作用域对象的 a 属性赋值的话,问题就出来了。 inner.a = inner.a + 1; 这个语句实际上进行了前面说的查找 a 属性值的过程,然后将返回的值赋值给了内部作用域对象的 a 属性,由于 a 属性是不存在的,因此创建了一个 a 的基本类型值属性,屏蔽了外层作用域对象 outer 中的 a 属性,这个坑就这么出来了。

因此,如果我们将基本类型值属性换成引用类型值属性的话,问题就能够得到解决,因为他们两个对象对应的属性是引用的同一个引用类型值,不管在哪对它进行修改都会反应在所有引用他的对象上。

总结

以上就是关于Angular中作用域需要注意的坑的全部内容,希望本文的内容对大家学习Angular中的作用域能有所帮助。

[!--infotagslink--]

相关文章

  • 浅析AngularJS Filter用法

    系统的学习了一下angularjs,发现angularjs的有些思想根php的模块smarty很像,例如数据绑定,filter。如果对smarty比较熟悉的话,学习angularjs会比较容易一点,这篇文章给大家介绍angularjs filter用法详解,感兴趣的朋友一起学习吧...2015-12-29
  • AngularJS 实现按需异步加载实例代码

    AngularJS 通过路由支持多视图应用, 可以根据路由动态加载所需的视图, 在 AngularJS 的文档中有详细的介绍, 网上也有不少教程, 就不用介绍了!随着视图的不断增加,js文件会越来越多,而 AngularJS 默认需要把全部的js都一次性...2015-10-21
  • AngularJS实现分页显示数据库信息

    这篇文章主要为大家详细介绍了AngularJS实现分页显示数据库信息效果的相关资料,感兴趣的小伙伴们可以参考一下...2016-07-06
  • angularjs $http实现form表单提交示例

    这篇文章主要介绍了angularjs $http实现form表单提交示例,非常具有实用价值,需要的朋友可以参考下 ...2017-06-15
  • AngularJS实现Model缓存的方式

    这篇文章主要介绍了AngularJS实现Model缓存的方式,分享了多种AngularJS实现Model缓存的方法,感兴趣的小伙伴们可以参考一下...2016-02-05
  • AngularJS自定义指令之复制指令实现方法

    这篇文章主要介绍了AngularJS自定义指令之复制指令实现方法,结合完整实例形式分析了AngularJS自定义指令实现复制功能的相关操作技巧,需要的朋友可以参考下...2017-05-22
  • AngularJS 视图详解及示例代码

    本文主要介绍AngularJS 视图,这里整理了相关知识,并附代码示例和实现效果图,有兴趣的小伙伴可以参考下...2016-08-27
  • AngularJS 依赖注入详解及示例代码

    本文主要介绍AngularJS 依赖注入的知识,这里整理了相关的基础知识,并附示例代码和实现效果图,有兴趣的小伙伴可以参考下...2016-08-24
  • 浅谈AngularJs指令之scope属性详解

    下面小编就为大家带来一篇浅谈AngularJs指令之scope属性详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
  • AngularJs中route的使用方法和配置

    angular是Google开发的一个单页面应用框架,是现在比较主流的单页面应用框架之一,下面通过本文给大家介绍AngularJs中route的使用方法和配置,感兴趣的朋友一起学习吧...2016-02-09
  • 详解JavaScript的AngularJS框架中的作用域与数据绑定

    这篇文章主要介绍了JavaScript的AngularJS框架中的作用域与数据绑定,包括作用域的继承以及数据的单向和双向绑定等重要知识点,需要的朋友可以参考下...2016-03-07
  • 快速学习AngularJs HTTP响应拦截器

    任何时候,如果我们想要为请求添加全局功能,例如身份认证、错误处理等,在请求发送给服务器之前或服务器返回时对其进行拦截,是比较好的实现手段...2016-01-05
  • AngularJS使用ngOption实现下拉列表的实例代码

    这篇文章主要介绍了AngularJS使用ngOption实现下拉列表的实例代码的相关资料,需要的朋友可以参考下...2016-01-25
  • Angularjs中如何使用filterFilter函数过滤

    这篇文章主要介绍了Angularjs中如何使用filterFilter函数过滤的相关资料,需要的朋友可以参考下...2016-02-12
  • AngularJS 让人爱不释手的八种功能

    AngularJS 让人爱不释手的八种功能,想知道AngularJS哪八种功能让人喜欢就快点看下本文吧...2016-03-28
  • AngularJS内建服务$location及其功能详解

    这篇文章主要为大家详细介绍了AngularJS内建服务$location及$location功能,感兴趣的小伙伴们可以参考一下...2016-07-06
  • AngularJS表单详解及示例代码

    本文主要介绍AngularJS表单的知识,这里整理了表单的基础知识和简单的示例代码,有需要的小伙伴可以参考下...2016-08-24
  • Angularjs---项目搭建图文教程

    下面小编就为大家带来一篇Angularjs---项目搭建图文教程。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-07-25
  • AngularJS中的指令实践开发指南(二)

    这篇文章主要介绍了AngularJS中的指令实践指南(二)的相关资料,需要的朋友可以参考下...2016-03-22
  • angularjs循环对象属性实现动态列的思路详解

    这篇文章主要介绍了angularjs循环对象属性实现动态列的思路详解,本文给大家分享一个demo代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-11-02