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中的作用域能有所帮助。
本文向大家介绍Go语言WaitGroup使用时需要注意的坑,包括了Go语言WaitGroup使用时需要注意的坑的使用技巧和注意事项,需要的朋友参考一下 前言 WaitGroup在go语言中,用于线程同步,单从字面意思理解,wait等待的意思,group组、团队的意思,WaitGroup就是指等待一组,等待一个系列执行完成后才会继续向下执行。Golang 中的 WaitGroup 一直是同步 gor
本文向大家介绍Javascript中3个需要注意的运算符,包括了Javascript中3个需要注意的运算符的使用技巧和注意事项,需要的朋友参考一下 平时写惯了C#,所以会觉得什么样的运算符就应该做什么样的运算,但是有一天你的习惯被其他语言颠覆了,不知道是不是有一股强大的好奇 心,刚好在js中,我的这种习惯就被颠覆了,下面就看看哪些运算符颠覆了我的三观。 一:==运算符 ==运算符之所以可以颠覆
本文向大家介绍JavaScript中使用typeof运算符需要注意的几个坑,包括了JavaScript中使用typeof运算符需要注意的几个坑的使用技巧和注意事项,需要的朋友参考一下 typeof是一个运算符,它对操作数返回的结果是一个字符串,有6种(只针对ES,不包含HOST环境对象)。 1.'undefined' 2.'boolean' 3.'string' 4.'number' 5.'obj
本文向大家介绍SpringBoot中打war包需要注意事项,包括了SpringBoot中打war包需要注意事项的使用技巧和注意事项,需要的朋友参考一下 最近在做一个项目,遇到了项目打成 war 包的一个问题,项目创建时选择的时 jar 包方式,后因项目部署要求,需要打成 war 包部署,遇到很多坑,在此做一下记录 一、修改打包方式 原: 改后: 二、排除内置 Tomcat 原: 改后: 使用 排除
本文向大家介绍使用 kafka 集群需要注意什么?相关面试题,主要包含被问及使用 kafka 集群需要注意什么?时的应答技巧和注意事项,需要的朋友参考一下 集群的数量不是越多越好,最好不要超过 7 个,因为节点越多,消息复制需要的时间就越长,整个群组的吞吐量就越低。 集群数量最好是单数,因为超过一半故障集群就不能用了,设置为单数容错率更高。
本文向大家介绍跟我学习javascript的prototype使用注意事项,包括了跟我学习javascript的prototype使用注意事项的使用技巧和注意事项,需要的朋友参考一下 一、在prototype上保存方法 不使用prototype进行JavaScript的编码是完全可行的,例如: 当创建了多个User类型的实例时,就存在问题了:不仅是name和passwordHash属性在每个实例上