angular脏检查机制,及指令中修改$scope致父级作用域无法接收到问题

广告位招租
扫码页面底部二维码联系

angular的指令很像我们所说的组件,【版权所有】唐霜 www.tangshuang.net【转载请注明来源】不过比较好玩的是,angular里面存在本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。作用域继承。不过这篇文章不讲这个问题,关著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。于angular作用域继承,可以阅读这篇著作权归作者所有,禁止商业用途转载。文章。本文要讲的是另外一个话题,即指令中【原创不易,请尊重版权】【原创内容,转载请注明出处】修改$scope的某个属性时,父级作用域本文作者:唐霜,转载请注明出处。【未经授权禁止转载】没有接收到这个修改。

未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】【原创内容,转载请注明出处】

问题还原【本文受版权保护】

【原创内容,转载请注明出处】原创内容,盗版必究。【转载请注明来源】【原创不易,请尊重版权】原创内容,盗版必究。

在开发中,我使用了如下的一套方法:【版权所有】唐霜 www.tangshuang.net

本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。
// controllerA
module.exports = ['$scope', function($scope) {
  $scope.members = []
  $scope.$watch('members', newValue => console.log(newValue))
}]
// template
<ul>
  <li ng-repeat="m in members">{{m.name}}</li>
</ul>
<button members="members">xxx</botton>
// directiveB
module.exports = [function() {
  return {
    restrict: 'A',
    scope: {
      members: '='
    },
    link($scope, $element, $attrs) {
      $element.on('click', () => { $scope.members = $scope.members.filter(item => item.age > 12) })
      $scope.$on('$destroy', () => { $element.off('click') })
    }
  }
}]

我希望通过点击自己创建的directiv【原创内容,转载请注明出处】【作者:唐霜】e,可以对memebrs进行过滤。然而,本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。当我在视图中点击时,什么事情都没有发生。

【原创不易,请尊重版权】未经授权,禁止复制转载。未经授权,禁止复制转载。【原创不易,请尊重版权】

angular的作用域【原创内容,转载请注明出处】

【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。【作者:唐霜】本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net

简单理解angular的作用域,即脚本$本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】scope的属性(或方法)可以在一个HT转载请注明出处:www.tangshuang.net【版权所有,侵权必究】ML结构范围内直接调用,调用方式有绑定(【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。如ng-click=”clo【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.netse()”中的close()【原创不易,请尊重版权】【版权所有,侵权必究】)和插值(如{{text}})两种。怎么【转载请注明来源】【未经授权禁止转载】生成一个作用域呢?最常用的就是在标签上加转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】ng-app和ng-controller【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。指令,另外还有ng-repeat、ng-转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。include、ng-switch、ng【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。-view可以创建作用域。当某些标签使用本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。了上述指令之后,这个标签范围内的HTML转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】结构,就可以调用指令对应脚本内的$sco【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】pe属性,一般一个应用内ng-app对应【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】的作用域变量是$rootScope,也就【本文受版权保护】著作权归作者所有,禁止商业用途转载。是最顶层的作用域,在ng-app内部创建本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。的任何作用域都可以继承$rootScop本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】e。

【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】

作用域继承【作者:唐霜】

【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】

有关angular作用域继承问题的文章非【本文首发于唐霜的博客】【作者:唐霜】常多,文章开头也给了一个链接。这里,我想转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net着重强调“继承”的本质和angular的【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net规律。

原创内容,盗版必究。本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net【作者:唐霜】

首先,我们讲的继承,实际上是表达“可以直【本文首发于唐霜的博客】【转载请注明来源】接用”这个想法。所谓可以直接用,就是不需【本文受版权保护】【版权所有,侵权必究】要你在脚本的$scope上加一个父级作用原创内容,盗版必究。本文作者:唐霜,转载请注明出处。域已经声明过的值,直接在HTML结构范围【原创不易,请尊重版权】原创内容,盗版必究。内使用即可。例如:

本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】【原创内容,转载请注明出处】【版权所有,侵权必究】【未经授权禁止转载】
<div ng-controller="ParentController">
  <div ng-controller="ChildController">
    <span>{{textFromParentController}}</span>
  </div>
</div>

在ChildController对应的H【关注微信公众号:wwwtangshuangnet】【本文受版权保护】TML结构范围内,仍然可以使用Paren转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.nettController里面的$scope【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】.textFromParentContr转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。oller这个值。因此,在实际使用的时候未经授权,禁止复制转载。【转载请注明来源】,不要把“继承”理解的太过复杂。

【版权所有】唐霜 www.tangshuang.net【本文受版权保护】【版权所有,侵权必究】

其次,作用域继承的本质,是子作用域创建或原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。实例化时,对父作用域里面$scope的引原创内容,盗版必究。本文作者:唐霜,转载请注明出处。用,就和JavaScript的proto【原创不易,请尊重版权】原创内容,盗版必究。type继承一摸一样,当在子作用域里面定本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net义了一个和父作用域同名的值时,它就覆盖了【本文首发于唐霜的博客】未经授权,禁止复制转载。父作用域该同名值的引用,也就脱离了父级作【作者:唐霜】本文版权归作者所有,未经授权不得转载。用域的控制。这样说还是太抽象,我们用为代未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。码来解释:

转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net
$parent.name = 'david'
$parent.age = 13

$scope.name = 'tom'
// 此时$scope.age自动获得13,这个过程相当于:
// $scope.prototype = $parent // 这是伪代码
// $scope.name = 'tom'
// 因此,当你改了$parent.age的时候,$scope.age也变了,但当你改$parent.name的时候,对$scope没有影响

总之,抛开一些特殊情况(上面提到的特殊内【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】置指令),angular的普通作用域继承【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】是非常简单且容易理解的,甚至都不需要思考【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】,而且在HTML里面写作用域的值(或调用【本文受版权保护】【未经授权禁止转载】)非常自然,你不需要思考或顾虑太多,因为【本文首发于唐霜的博客】【本文受版权保护】你可以非常容易的觉察到哪些值是可以用的,【作者:唐霜】【原创内容,转载请注明出处】哪些是不可以的。

【转载请注明来源】本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。原创内容,盗版必究。

指令的作用域【转载请注明来源】

本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。

angular出色的扩展功能非指令莫属。著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】但是指令的作用域又有点复杂。

本文版权归作者所有,未经授权不得转载。【转载请注明来源】转载请注明出处:www.tangshuang.net【未经授权禁止转载】

首先,我们要知道指令的作用域到底是什么?【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net因为对于HTML文档中而言,一个ng指令【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net其实就是一个标签或属性,它不是一个完整的本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】HTML结构范围,何来作用域之说呢?但是未经授权,禁止复制转载。原创内容,盗版必究。它的脚本里面又有$scope,那么这个$【本文受版权保护】本文作者:唐霜,转载请注明出处。scope到底是用在什么地方的呢?实际上本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net,指令的脚本里面的$scope不是对使用【版权所有,侵权必究】【本文首发于唐霜的博客】指令的HTML文档而言,而是指令自己内部【作者:唐霜】【本文受版权保护】的templete内可用。比如说:

【未经授权禁止转载】转载请注明出处:www.tangshuang.net【版权所有,侵权必究】【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net
// controller.html
<div my-directive></div>
// my-directive.html
<span>{{text}}</span>

我们创建一个my-directive指令本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net,而my-directive内使用tem未经授权,禁止复制转载。原创内容,盗版必究。plateUrl使用my-directi著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netve.html作为模板,因此,在my-d【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】irective.js脚本里面的$sco【原创内容,转载请注明出处】【原创不易,请尊重版权】pe对my-directive.html本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】内的插值或调用有效。

本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】

其次,指令作用域的继承问题。【本文受版权保护】

【作者:唐霜】【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net【转载请注明来源】【本文首发于唐霜的博客】

在创建一个指令的时候,我们在指令的创建函【作者:唐霜】未经授权,禁止复制转载。数返回值中,有一个scope选项:

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net
module.exports = function() {
  return {
    restrict: 'A',
    scope: true,
  }
}

这里的scope选项就是用来确定,指令外未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。部的作用域和指令内部的作用域之间的关系。本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。默认情况下,scope:false,表示【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】共享父作用域,也就是说指令内部的$sco【作者:唐霜】本文作者:唐霜,转载请注明出处。pe直接是指令所依附的那个标签所在的作用【版权所有,侵权必究】【原创内容,转载请注明出处】域的$scope(即JavaScript著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。里面的object引用),因此,无论是外【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。部的$scope发生变化,还是指令内部的【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】$scope值发生变化,两边都是同步的,【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】也就会引起界面的变化,不过这种共享作用域原创内容,盗版必究。【原创不易,请尊重版权】常常遇到一些不可预料的问题,所以很少直接【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。用。而当scope:true,表示继承父【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】作用域,继承模式也是原型继承,也就是说,本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。在指令内的$scope默认拥有指令依附的【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】那个标签所在的作用域的$scope值,当本文版权归作者所有,未经授权不得转载。【作者:唐霜】然,如果你在指令内部修改了$scope的【转载请注明来源】转载请注明出处:www.tangshuang.net某个属性,那么这个属性值将覆盖外部作用域原创内容,盗版必究。【本文首发于唐霜的博客】对应的属性值。

【原创内容,转载请注明出处】未经授权,禁止复制转载。未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。

当思路到这里的时候,一个自然而然的问题浮本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】现了。如果在$scope默认没有值的情况【未经授权禁止转载】【未经授权禁止转载】下,会自动继承父级$scope的值,但是【转载请注明来源】转载请注明出处:www.tangshuang.net如果我新设了一个属性值覆盖了父级$sco【作者:唐霜】【关注微信公众号:wwwtangshuangnet】pe的属性值,父级$scope对应属性值【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。再变时,会不会影响当前这个$scope被原创内容,盗版必究。本文作者:唐霜,转载请注明出处。设置的新值?

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net

这个答案是显而易见的:【关注微信公众号:wwwtangshuangnet】在你没有设那个属性值之前,修改父$sco【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。pe对应属性,子作用域继承了父作用域,那【原创不易,请尊重版权】【作者:唐霜】个属性值是跟着变的,界面也随着变化。但是本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。,一旦当你设置了新值的那一刻,继承关系就【作者:唐霜】【版权所有】唐霜 www.tangshuang.net断了,这个属性将不再相互影响,子作用域当转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。然不会影响父作用域,同时,父作用域也不会【转载请注明来源】【关注微信公众号:wwwtangshuangnet】影响子作用域。实际上,理解这一点,用JavaScrip【版权所有,侵权必究】【转载请注明来源】t的原型链继承是再适合不过的,这就考你的本文作者:唐霜,转载请注明出处。【转载请注明来源】基础功了。

【未经授权禁止转载】【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】
【本文首发于唐霜的博客】【版权所有,侵权必究】转载请注明出处:www.tangshuang.net

除了把指令的scope选项设置为true【转载请注明来源】【作者:唐霜】|false之外,还可以设置为一个{},本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net例如:

本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【本文受版权保护】
return {
  restrict: 'A',
  scope: {
    name: '@name',
    age: '=age',
    sing: '&sing',
    father: '@',
    mother: '@?',
  },
}

上面5种情况分别代表了5种表达方式,但表【版权所有】唐霜 www.tangshuang.net【作者:唐霜】达与外部作用域关系的,只有3种,现在一一【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。解释。

【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】【作者:唐霜】

‘@name’表【转载请注明来源】【版权所有,侵权必究】示这个指令所依附的标签接受一个name属【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net性,这个name属性传入的值,是一个字符原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。串,字符串将作为当前指令里面的$scop著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。e的某属性值,在当前作用域修改这个值,不【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。会影响外部作用域的对应值,举个例子:

转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】
// 外部
<div pass-value="myName"></div> // 即使你的$scope.myName = 'tomy',directive内部接收到的也是myName这个字符串
<div pass-value="{{myName}}"></div> // 你的$scope.myName = 'lucy', 那么directive内部接收到的就是lucy

‘=age’表示本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】接受age属性,并且把它的值当作一个变量【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】,实现穿透(继承本文版权归作者所有,未经授权不得转载。),在当前作用域修改这个变量,会影响外部【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】作用域对应的变量值,例如:

【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】
// 外部
<div pass-value="myValue"> // 其中myValue={ name: 'tomy' }

// directive内部
{
  template: '<a href="#" ng-click="onClick()">xxx</a>',
  scope: {
    value: '=passValue',
  },
  link($scope) {
    $scope.onClick = function() {
      $scope.value.name = 'lucy'
    }
  },
}

当点击指令内的链接时,外部作用域的myV【本文首发于唐霜的博客】【原创内容,转载请注明出处】alue.name也被修改了。这是js数未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。据类型决定的。但是要注意,如果你直接修改$scope.value = { name: 'lucy' },则不会产生任何结果,并且,这样pass【原创不易,请尊重版权】【作者:唐霜】Value和$scope.value的引著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。用关系段了,对$scope.value的【本文受版权保护】本文作者:唐霜,转载请注明出处。任何修改都不会再影响外部作用域都myVa【本文受版权保护】【本文受版权保护】lue,因此要特别注意这一点。

【版权所有,侵权必究】原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】

‘&singR原创内容,盗版必究。未经授权,禁止复制转载。17;表示接受sing属性,但是sing【版权所有,侵权必究】原创内容,盗版必究。属性的值必须是一个函数【原创不易,请尊重版权】,而且和=一样,它是一个【转载请注明来源】继承未经授权,禁止复制转载。的值。转载请注明出处:www.tangshuang.net

未经授权,禁止复制转载。【未经授权禁止转载】【原创内容,转载请注明出处】

‘@’表示接受一本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】个father属性,之所以在@后面省略内【转载请注明来源】【版权所有】唐霜 www.tangshuang.net容,是因为这个属性值跟前面的father【转载请注明来源】原创内容,盗版必究。是一模一样的,而前面那些@name, =【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。age,都可以不一样,比如可以是@my-著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】name, =my-age,外部标签的属【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。性名和内部$scope的属性名不同,但具【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net有对应关系。

【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。【本文受版权保护】未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】

‘@?’表示可以转载请注明出处:www.tangshuang.net原创内容,盗版必究。接受一个mother属性,也可以不传,?【未经授权禁止转载】【本文首发于唐霜的博客】的意思就是可选。

【转载请注明来源】【转载请注明来源】原创内容,盗版必究。【作者:唐霜】

如上所述,实际上,指令内部的$scope【作者:唐霜】【本文受版权保护】属性通过3个特殊的符号和外部作用域上的值【转载请注明来源】【本文首发于唐霜的博客】进行绑定,你只需要分清楚@传进来的一定是未经授权,禁止复制转载。【原创不易,请尊重版权】字符串即可。

【本文受版权保护】转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。

脏检查和双向绑定【未经授权禁止转载】

【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】未经授权,禁止复制转载。【本文首发于唐霜的博客】

我们经常听到angular的脏检查机制和【转载请注明来源】著作权归作者所有,禁止商业用途转载。数据的双向绑定,这两个词似乎已经是它的代原创内容,盗版必究。【转载请注明来源】名词了。那么从编程层面,这到底是什么鬼?

【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。

当$scope的一个属性被改变时,界面可【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net能会更新。那么为什么angular里面,【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。修改$scope上的一个属性,可以引起界【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net面的变化呢?这是angular的数据响应【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。机制决定的。在angular里面就是脏检【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】查机制。而脏检查,和双向绑定离不开。

【作者:唐霜】【作者:唐霜】【转载请注明来源】【未经授权禁止转载】

这里插句题外话,JavaScript里面【版权所有,侵权必究】原创内容,盗版必究。非常有意思的一种接口,当你修改(或新增)【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net一个对象的某个属性时,会触发该对象里面的【关注微信公众号:wwwtangshuangnet】【本文受版权保护】setter。如果你对这块不是很了解,可【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】以先学一下Object.definePropert本文版权归作者所有,未经授权不得转载。【本文受版权保护】y,包括这两年超级火的vuejs也是通过这未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。个接口实现的。它是一个ES5的标准接口,著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net据说IE8以下的浏览器都可能支持。

原创内容,盗版必究。原创内容,盗版必究。本文作者:唐霜,转载请注明出处。原创内容,盗版必究。

我们可以设计一种实现,当你修改或赋值$s本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netcope的某个属性时,就触发了$scop原创内容,盗版必究。原创内容,盗版必究。e这个js对象的setter,我们可以自【关注微信公众号:wwwtangshuangnet】【本文受版权保护】定义这个setter,它是一个函数,在这本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。个函数内部,调用某些逻辑去更新界面。同时【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】,为了确保新塞进来的对象也可以被监听到变【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】化,在你赋值时,还要把赋值进来的对象也进【版权所有,侵权必究】【本文首发于唐霜的博客】行改造,改造为可以被监听的对象。

【原创内容,转载请注明出处】【作者:唐霜】转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】
【原创内容,转载请注明出处】【转载请注明来源】【本文受版权保护】

双向绑定顾名思义是两个过程,一个是将$s本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。cope属性值绑定到HTML结构中,当$【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.netscope属性值发生变化的时候界面也发生本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。变化;另一个是,当用户在界面上进行操作,【原创内容,转载请注明出处】未经授权,禁止复制转载。例如点击、输入、选择时,自动触发$sco【本文受版权保护】【未经授权禁止转载】pe属性的变化(界面也可能跟着变)。而脏未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】检查的作用是“在当$scope属性值发生【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】变化的时候促使界面发生变化”。

著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。

angular的数据响应机制本文作者:唐霜,转载请注明出处。

【作者:唐霜】原创内容,盗版必究。【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。

那么,在代码层面,angular是怎么做【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。到监听数据变动然后更新界面的呢?答案是,【原创不易,请尊重版权】【未经授权禁止转载】angular根本不监听数据的变动,而是未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。在恰当的时机从$rootScope开始遍转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。历所有$scope,检查它们上面的属性值本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。是否有变化,如果有变化,就用一个变量di本文作者:唐霜,转载请注明出处。【本文受版权保护】rty记录为true,再次进行遍历,如此【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】往复,直到某一个遍历完成时,这些$sco【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】pe的属性值都没有变化时,结束遍历。由于著作权归作者所有,禁止商业用途转载。【本文受版权保护】使用了一个dirty变量作为记录,因此被未经授权,禁止复制转载。未经授权,禁止复制转载。称为脏检查机制。

【作者:唐霜】著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。

这里面有三个问题:【访问 www.tangshuang.net 获取更多精彩内容】

【本文受版权保护】本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net
  1. “恰当的时机”是什么时候?【未经授权禁止转载】
  2. 转载请注明出处:www.tangshuang.net【未经授权禁止转载】未经授权,禁止复制转载。
  3. 如何做到知道属性值是否有变化?【原创不易,请尊重版权】
  4. 本文版权归作者所有,未经授权不得转载。【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。
  5. 这个遍历循环是怎么实现的?【版权所有,侵权必究】
  6. 【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。原创内容,盗版必究。

要解决这三个问题,我们需要深入了解ang本文作者:唐霜,转载请注明出处。【未经授权禁止转载】ular的$watch, $apply,【本文受版权保护】【本文首发于唐霜的博客】 $digest。

著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。

$watch绑定要检查的值【关注微信公众号:wwwtangshuangnet】

【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】著作权归作者所有,禁止商业用途转载。

简单的说,当一个作用域创建的时候,ang【本文受版权保护】【版权所有】唐霜 www.tangshuang.netular会去解析模板中当前作用域下的模板【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】结构,并且自动将那些插值(如{{text【原创内容,转载请注明出处】【原创不易,请尊重版权】}})或调用(如ng-model=【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。221;age”)找出来,并著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】利用$watch建立绑定,它的回调函数用【转载请注明来源】【原创不易,请尊重版权】于决定如果新值和旧值不同时(或相同时)要本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net干什么事。当然,你也可以手动在脚本里面使【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net用$scope.$watch对某个属性进【本文受版权保护】【关注微信公众号:wwwtangshuangnet】行绑定。它的使用方法如下:

【版权所有】唐霜 www.tangshuang.net【作者:唐霜】转载请注明出处:www.tangshuang.net
$scope.$watch(string|function, listener, objectEquality, prettyPrintExpression)

第一个参数是一个字符串或函数,如果是函数著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。,需要运行后得到一个字符串,这个字符串用【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】于确定将绑定$scope上的哪个属性。l本文作者:唐霜,转载请注明出处。【本文受版权保护】istener则是回调函数,表示当这个属【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】性的值发生变化时,执行该函数。objec未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。tEquality是一个boolean,【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】为true的时候,会对object进行深【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】检查(懂什么叫深拷贝的话就懂深检查)。第【未经授权禁止转载】【原创不易,请尊重版权】四个参数是如何解析第一个参数的表达式,使本文作者:唐霜,转载请注明出处。原创内容,盗版必究。用比较复杂,一般不传。

【未经授权禁止转载】【转载请注明来源】【本文受版权保护】【本文受版权保护】原创内容,盗版必究。

$digest遍历递归【本文受版权保护】

【版权所有】唐霜 www.tangshuang.net【转载请注明来源】【版权所有】唐霜 www.tangshuang.net【转载请注明来源】

当使用$watch绑定了要检查的属性之后本文作者:唐霜,转载请注明出处。【本文受版权保护】,当这个属性发生变化,就会执行回调函数。【版权所有,侵权必究】原创内容,盗版必究。但是前面已经说过了,angular里面没著作权归作者所有,禁止商业用途转载。【作者:唐霜】有监听这么一说。它没有用object的s本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netetter机制(angular2之后改进【原创内容,转载请注明出处】【本文受版权保护】并采用了这个机制),而是脏检查机制。脏检【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net查的核心,就是$digest循环。当用户【转载请注明来源】【原创不易,请尊重版权】执行了某些操作之后,angular内部会【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net调用$digest(),最终导致界面重新转载请注明出处:www.tangshuang.net【本文受版权保护】渲染。那么它究竟是怎么一回事呢?

原创内容,盗版必究。【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】【原创内容,转载请注明出处】

调用$watch之后,对应的信息被绑定到【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】angular内部的一个$$watche本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。rs中,它是一个队列(数组),而当$di【转载请注明来源】本文版权归作者所有,未经授权不得转载。gest被触发时,angular就会去遍【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net历这个数组,并且用一个dirty变量记录【本文受版权保护】【原创不易,请尊重版权】$$watchers里面记录的那些$sc【作者:唐霜】【本文受版权保护】ope属性是否有变化,当有变化的时候,d原创内容,盗版必究。【转载请注明来源】irty被设置为true,在$diges【本文受版权保护】【版权所有,侵权必究】t执行结束的时候,它会再检查dirty,【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。如果dirty为true,它会再调用自己【未经授权禁止转载】【未经授权禁止转载】,直到dirty为true。但是为了防止【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】死循环,angular规定,当递归发生了【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】10次或以上时,直接抛出一个错误,并跳出转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】循环。

【作者:唐霜】【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】

递归流程如下:本文作者:唐霜,转载请注明出处。

【本文受版权保护】【原创不易,请尊重版权】原创内容,盗版必究。本文作者:唐霜,转载请注明出处。【作者:唐霜】
  1. 判断dirty是否为true,如果为fa【原创内容,转载请注明出处】【转载请注明来源】lse,则不进行$digest递归。(d原创内容,盗版必究。【原创内容,转载请注明出处】irty默认为true)
  2. 【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】
  3. 遍历$$watchers,取出对应的属性【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net值的老值和新值
  4. 【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net【本文受版权保护】
  5. 根据objectEquality进行新老转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。值的对比。
  6. 【转载请注明来源】本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】【转载请注明来源】
  7. 如果两个值不同,则继续往下执行。如果两个【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。值相同,则设置dirty为false,跳转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】出递归。
  8. 【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。
  9. 设置dirty为true【版权所有】唐霜 www.tangshuang.net
  10. 【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net【作者:唐霜】【关注微信公众号:wwwtangshuangnet】【本文受版权保护】
  11. 用新值代替老值,这样,在下一轮递归的时候本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。,老值就是这一轮的新值
  12. 【本文首发于唐霜的博客】【本文首发于唐霜的博客】【作者:唐霜】未经授权,禁止复制转载。【原创不易,请尊重版权】
  13. 再次调用$digest【本文受版权保护】
  14. 【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net

当递归流程结束之后,$digest还要执【原创不易,请尊重版权】【转载请注明来源】行:

原创内容,盗版必究。【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】
  1. 将变化后的$scope重新渲染到界面著作权归作者所有,禁止商业用途转载。
  2. 【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。【版权所有,侵权必究】

当一个作用域创建完之后,$scope.$【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.netdigest会被运行一次。dirty的默【本文受版权保护】转载请注明出处:www.tangshuang.net认值被设定为true,因此,如果你在co【原创不易,请尊重版权】转载请注明出处:www.tangshuang.netntroller里面使用了$watch,著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】并且进行了属性赋值,往往刷新页面就可以看【原创不易,请尊重版权】【转载请注明来源】到$watch的回调函数被执行了。但是,【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net现在问题来了,上面说的“angular内未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。部会调用$digest()”,这个内部是未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】怎么实现的?

原创内容,盗版必究。【作者:唐霜】【原创不易,请尊重版权】【版权所有,侵权必究】

$apply触发$digest【版权所有】唐霜 www.tangshuang.net

转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】

在我们自己编程时,并不直接使用$dige原创内容,盗版必究。转载请注明出处:www.tangshuang.netst,而是调用$scope.$apply【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】(),$apply内部会触发$diges【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。t递归遍历。同时,你可以给$apply传本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】一个参数,是个函数,这个函数会在$dig本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。est开始之前执行。现在回到上面的问题,著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】angular内部怎么触发$digest【转载请注明来源】本文版权归作者所有,未经授权不得转载。?实际上,angular里面要求你通过n著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】g-click, ng-modal, n【原创内容,转载请注明出处】【本文受版权保护】g-keyup等来进行数据的双向绑定,为著作权归作者所有,禁止商业用途转载。【转载请注明来源】什么,因为这些angular的内部指令封著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】装了$apply,比如ng-click,【原创内容,转载请注明出处】【原创内容,转载请注明出处】它其实包含了document.addEv【版权所有】唐霜 www.tangshuang.net【转载请注明来源】entListener(‘c【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】lick’)和$scope.【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】$apply()两个过程。所谓的数据双向原创内容,盗版必究。【版权所有,侵权必究】绑定,其实也就是ng-input和$sc本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】ope.$apply的同时运行。

【版权所有,侵权必究】未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net【转载请注明来源】【原创内容,转载请注明出处】

当用户在模板里面使用ng-click时,【本文受版权保护】原创内容,盗版必究。如下:

【未经授权禁止转载】未经授权,禁止复制转载。【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net
<div ng-click="update()">change</div>
$scope.update = function() {
  $scope.name = 'tom'
}

实际上,当用户点击之后,angular内【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net部还会执行$scope.$apply()【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】,从而触发$digest遍历递归,最终触【原创不易,请尊重版权】【未经授权禁止转载】发界面重绘。

转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】

手动调用$apply著作权归作者所有,禁止商业用途转载。

未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。【转载请注明来源】本文作者:唐霜,转载请注明出处。原创内容,盗版必究。

但是有些情况下,我们不可能直接使用ang原创内容,盗版必究。转载请注明出处:www.tangshuang.netular内部指令,有两种情况我们需要手动【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。调用$apply,一种是调用angula【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】r内置的语法糖,比如$http, $ti原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。meout,另一种是我们没有使用angu本文作者:唐霜,转载请注明出处。【作者:唐霜】lar内部机制去更新了$scope,比如本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】我们用$element.on(̵【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。6;click’, () =【版权所有,侵权必究】【本文首发于唐霜的博客】> $scope.name = &原创内容,盗版必究。【原创不易,请尊重版权】#8216;lucy’)。也【转载请注明来源】【版权所有】唐霜 www.tangshuang.net就是说“异步”和“机制外”修改$scop未经授权,禁止复制转载。【原创内容,转载请注明出处】e属性值之后,我们都要手动调用$appl【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】y,虽然我们在调用$timeout的时候本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net,没有手写$apply,但实际上它内部确【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】实调用了$apply:

著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【未经授权禁止转载】原创内容,盗版必究。
function($timeout) {
  // 当我们通过on('click')的方式触发某些更新的时候,可以这样做
  $timeout(() => {
    $scope.name = 'lily'
  })
  // 也可以这样做
  $element.on('click', () => {
    $scope.name = 'david'
    $scope.$apply()
  })
}

但是,一定要注意,在递归过程中,绝对不能【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。手动调用$apply,比如在ng-cli【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】ck的函数中,比如在$watch的回调函【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net数中。

【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】【作者:唐霜】

伪代码实现未经授权,禁止复制转载。

转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。【本文受版权保护】

通过上面的讲解,你可能已经对angula【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】r里面的脏检查已经了解了,但是我们还是希转载请注明出处:www.tangshuang.net【本文受版权保护】望更深入,用代码来把事情说清楚。我这里不【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】去抄写angular的源码,而是自己写一【转载请注明来源】【本文首发于唐霜的博客】段伪代码,这样更有助于理解整个机制。

【本文受版权保护】著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】
import { isEqual } from 'lodash'

class Scope {
  constructor() {
    this.$$dirty = true
    this.$$count = 0
    this.$$watchers = []
  }
  $watch(property, listener, deepEqual) {
    let watcher = {
      property,
      listener,
      deepEqual,
    }
    this.$$watchers.push(watcher)
  }
  $digest() {
    if (this.$$count >= 10) {
      throw new Error('$digest超过10次')
    }

    this.$$watchers.forEach(watcher => {
      let newValue = eval('return this.' + watcher.property)
      let oldValue = watcher.oldValue
      if (watcher.deepEqual && isEqual(newValue, oldValue)) {
        watcher.dirty = false
      } 
      else if (newValue === oldValue) {
        watcher.dirty = false
      }
      else {
        watcher.dirty = true
        eval('this.' + watcher.property + ' = ' newValue)
        watcher.listener(newValue, oldValue) // 注意,listener是在newValue赋值给$scope之后执行的
        watcher.oldValue = newValue
      }
      // 这里的实现和angular逻辑里面有一点不同,angular里面,当newValue和oldValue都为undefined时,listener会被调用,可能是angular里面在$watch的时候,会自动给$scope加上原本没有的属性,因此认为是一次变动
    })
    
    this.$$count ++

    this.$$dirty = false
    for (let watcher of this.$$watchers) {
      if (watcher.dirty) {
        this.$$dirty = true
        break
      }
    }

    if (this.$$dirty) {
      this.$digest()
    }
    else {
       this.$patch()
       this.$$dirty = true
       this.$$count = 0
    }
  }
  $apply() {
    if (this.$$count) {
      return // 当$digest执行的过程中,不能触发$apply
    }
    this.$$dirty = true
    this.$$count = 0
    this.$digest()
  }
  $patch() {
    // 重绘界面
  }
}
function ControllerRegister(controllerTemplate, controllerFunction) {
  let $scope = new Scope()
  $paser(controllerTemplate, $scope) // 解析controller的模板,把模板中的属性全部都解析出来,并且把这些属性赋值给$scope
  controllerFunction($scope) // 在controllerFunction内部可能又给$scope添加了一些属性,注意,不能在运行controllerFunction的时候调用$scope.$apply()

  let properties = Object.keys($scope) // 找出$scope上的所有属性
  // 要把$scope上的一些内置属性排除掉  
  properties = properties.filter(item => item.indexOf('$') !== 0) // 当然,这种排除方法只能保证在用户不使用$作为属性开头的时候有用

  properties.forEach(property => {
    $scope.$watch(property, () => {}, true)
  })

  $scope.$digest()
}

上面就是用伪代码实现了angular内部【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。的机制,不能作为真实的引擎去使用,但是体转载请注明出处:www.tangshuang.net原创内容,盗版必究。现了整个脏检查的实现思路。

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net【作者:唐霜】

问题的解决【原创内容,转载请注明出处】

【作者:唐霜】本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】【未经授权禁止转载】

我们回到文章开头的问题,那段代码的问题究原创内容,盗版必究。【原创内容,转载请注明出处】竟在哪里呢?通过本文的解释,你应该非常容本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】易知道,代码中使用了on(‘【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。click’)而没有调用$a【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.netpply,正确的做法是使用ng-clic【版权所有,侵权必究】【本文受版权保护】k。但是,出了这个问题,还有另外一个问题【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。,就是作用域的继承问题。

【未经授权禁止转载】未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。【作者:唐霜】

在directiveB中,直接使用$sc【本文受版权保护】【作者:唐霜】ope.members = newVal【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。ue,虽然看上去父级作用域里面的memb【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.neters应该也要等于新的值,但是我们从js本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】的角度出发来看下:

【原创不易,请尊重版权】【原创内容,转载请注明出处】【未经授权禁止转载】
directiveB.$scope.members = controllerA.$scope.members
directiveB.$scope.members = newMembers
controllerA.$scope.members = ?

显然,这是一个超出预期的结果,一切都是j【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】s里面object是引用型数据的锅。那么著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。要保证修改没问题,要怎么办呢?

【版权所有,侵权必究】【本文首发于唐霜的博客】【原创内容,转载请注明出处】
directiveB.$scope.members = controllerA.$scope.members
for (let i = 0; i < newMembers.length; i ++) {
  directiveB.$scope.members.splice(i, 1, newMembers[i])
}
controllerA.$scope.members = ?

当使用数组的时候,要格外小心,因为数组是【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】特殊的object,它比普通的objec著作权归作者所有,禁止商业用途转载。【本文受版权保护】t更加复杂。

【原创内容,转载请注明出处】【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。

好了,关于angular里面的一些用法就【未经授权禁止转载】【作者:唐霜】讲到这里。肯定有很多不足的地方,欢迎在下本文版权归作者所有,未经授权不得转载。【作者:唐霜】方留言和我交流。

【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。【本文受版权保护】著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】

2018-06-07 5373

为价值买单,打赏一杯咖啡

本文价值53.73RMB