angular中scope,controller,this继承区别

1.scope的几种继承

说到scope,我们可能会想到rootScope,因为所有的scope都是由rootScope产生出来的,我们也知道在angular里面 scope有几种继承形式:
1.scope为false,完成继承父的scope,子scope,父scope修改值都互相影响(其实同一scope下修改的是用一个值)
2.scope为true,子创建一个scope(注意此时和父是两个不用scope),但是还是继承父scope,怎么理解呢,拿个构造函数来说吧,我实例化这个constructor,那么实例化出来的对象应该是同时拥有constructor和prototype上的属性和方法,假如有个属性a在constructor和prototype都有,那么首先肯定先取constructor.a,constructor上没有,再取prototype.a,那么constructor可以比作子scope,prototype可以比作父scope,当子scope没有,再去父scope去取。
3.scope为{},那么此时创建一个独立的scope,和父scope是没有关系,两个scope都是互不想干的(此时有几种父传值给子的方式)

有了这些概念之后我们来看个例子:
html

<div ng-app="App">
    <parent-scope>
      <child-scope></child-scope>
    </parent-scope>
</div>

js

angular.module("App", [])
.directive("parentScope", function () {
    return {
        restrict: "ECAM",
        template: '<input type="text" ng-model="username"><child-scope></child-scope>',
        scope: false,
        controller: ['$scope', function ($scope) {
            $scope.username = '张三'
        }]
    }

})
.directive("childScope", function () {
    return {
        restrict: "ECAM",
        template: '<input type="text" ng-model="username">',
        replace: true,
        scope: false,
    }
})

结果:子scope继承父scope,并且互相影响!
在这里插入图片描述
然后把子的scope改成true,结果是当子scope无此属性,父可以影响到子,当子scope有此属性,父影响不到子,子也影响不到父!
在这里插入图片描述
最后把子的scope改成{},那就毫无疑问,两者互不影响!

2.controller继承

可能看到controller继承有点懵?没听过controller继承?还是拿个上面例子来说,稍微改了下:

angular.module("App", [])
.directive("parentScope", function () {
    return {
        restrict: "ECAM",
        template: '<input type="text" ng-model="ctrl.username"><child-scope></child-scope>',
        scope: false,
        controllerAs:'ctrl',
        controller: ['$scope', function ($scope) {
            var ctrl = this;
            ctrl.username = '张三'
        }]
    }

})
.directive("childScope", function () {
    return {
        restrict: "ECAM",
        template: '<input type="text" ng-model="ctrl.username">',
        replace: true,
        scope: true,
    }
})

我把username绑到controller上,然后把子scope改成true,想下结果是什么?很多人认为可能和scope一样的吧,ctrl是在scope里面的,应该和scope继承一样,但是结果不是一样,是子scope为false结果一样,互相影响!无论改变哪个scope值,都会一起变化!
在这里插入图片描述
为什么会是这样的?
还记得scope是怎么创建的和怎么继承的吗?(不了解的可以点击这里
这里我大概说下,首先创建的是rootScope(根作用域),然后创建子scope,创建子scope时候会判断此scope是否是隔离的,如果是不是隔离就会继承父scope,ChildScope.prototype = parent,如果是隔离的就new scope ,此时和原型继承毫无关系了。上段源代码:

 $new: function (isolate, parent) {
   var child;
   parent = parent || this;
   //是否是隔离scope
   if (isolate) {
   	 //此时和原型继无关
     child = new Scope();
     child.$root = this.$root;
   } else {
   //判断是否有
     if (!this.$$ChildScope) {
      //子构造函数的创建并继承父
       this.$$ChildScope = createChildScopeClass(this);
     }
     //子作用域的创建
     child = new this.$$ChildScope();
   }
   //把自己的父,兄弟姐妹,儿子整明白(要不然乱套了)
   child.$parent = parent;
   // 孩子的前一个兄弟节点为父亲的最后一个孩子
   child.$$prevSibling = parent.$$childTail;
   
   if (parent.$$childHead) {
     parent.$$childTail.$$nextSibling = child;
     parent.$$childTail = child;
   } else {
     parent.$$childHead = parent.$$childTail = child;
   }
   
   if (isolate || parent !== this) child.$on('$destroy', destroyChildScope);
   return child;
 }

function createChildScopeClass(parent) {
  function ChildScope() {
    this.$$watchers = this.$$nextSibling =
      this.$$childHead = this.$$childTail = null;
    this.$$listeners = {};
    this.$$listenerCount = {};
    this.$$watchersCount = 0;
    this.$id = nextUid();
    this.$$ChildScope = null;
    this.$$suspended = false;
  }
  ChildScope.prototype = parent;
  return ChildScope;
}

上面有注释,已经原理很清楚了,那么再来看上面的例子,首先创建rootScope,parentScope指令创建的scope继承rootScope,也是就用一scope了,所以id都为1。而childScope创建的scope虽然也继承rootScope,但是它还是个创建了一个新的scope(因为scope=true)。
此图为parentScope(id为1):
在这里插入图片描述
此图为childScope(id为2):
在这里插入图片描述
因为parentScope里面创建了一个controller,所以你在parentScope图中可以看到有个ctrl属性,根据原型继承ChildScope.prototype = parentScope,那么ChildScope原型上必定有ctrl属性,我们来看看ChildScope的__proto__属性:
在这里插入图片描述
所以不管输入那边的,它们都互相都受影响!这是一种继承方式,下面我们再来说下另外一种获取controller方式(用的比较少,严格的说不能是继承,只是拿到这个controller)
这里我们需要用到$controller service(angualr内置服务),下面看下怎么实现的:
html:

<div ng-app="App">
    <div ng-controller="firstController">
        <inherit-test></inherit-test>
    </div>
</div>

js:

angular.module("App", [])
.controller("firstController", [function () {
    var ctrl = this;
    ctrl.name = "张三";
    ctrl.age = 18;
    ctrl.sex = '男';
}])
.directive("inheritTest", function () {
    return {
        restrict: "ECAM",
        controllerAs: 'ctrl',
        controller: ['$controller', '$scope', function ($controller, $scope) {
            var ctrl = this;
            ctrl.test = 'inherit';
            var test = $controller('firstController', {
                $scope: $scope
            })
            angular.extend(this, test);
            console.log(test); //age: 18 name: "张三" sex: "男" test: "inherit"
        }],
    }
})

这里就和scope没有关系,其实大概原理是angular会把注册的controller放到一个invokeQueue数组里面,此时并没有执行,等到 angular初始化时 angularInit(window.document, bootstrap),然后$ControllerProvider.register.apply($ControllerProvider,firstController);在register方法里面把所有注册的controller放到一个controllers对象里面,我们看下这个register源码(无关的代码去掉了):

  function $ControllerProvider() {
  	//装所有注册的controller的对象
    var controllers = {};
    //两个参数相当是('firstController',firstControllerConstructor)
    this.register = function (name, constructor) {
    	//判断名称是hasOwnProperty抛出错误
      assertNotHasOwnProperty(name, 'controller');
       //是对象的话就让controllers继承它
      if (isObject(name)) {
        extend(controllers, name);
      } else {
      //与firstController为key,firstControllerConstructor为value形式放到controllers里面
        controllers[name] = constructor;
      }
    };

所以我们可以根据controller注册名称可以去这个controllers对象里面找它。另外还有一种组件之间controller获取(用的是require,如果不懂的可以点击这里)。

3.this的指向

Controller是一个的构造函数,必须要new(实例化后)才能进行调用,所以必定会生成一个Controller实例,此实例也必然会继承构造函数中this绑定的所有属性与方法,此时的this指向的是Controller实例。再看下面代码:

angular.module("App", [])
.controller("firstController", ['$scope',function ($scope) {
   var ctrl = this;
   ctrl.name = "张三";
   ctrl.age = 18;
   ctrl.sex = '男';
   $scope.method =function(){
       console.log(this);//scope
   }
}])

从上面的代码可以看出,它们其实没什么联系,如果非要说有的话,那么它们都可以在同一个构造函数中互相访问,$scope是这个函数的形参,this是这个函数的上下文,所以它们绝对不是同一个对象。Controller中的this与$scope都可以存储数据,最好不要数据分散存储两个对象中。好了说到这里都已经说的差不多了,有不正的地方请指正,不胜感激!!欢乐的时光总是过得特别快,又到时候和大家讲拜拜!!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值