Angular JS - $scope

Edit

$scope

Scope is an object that refers to the application model. It is an execution context for expressions. Scopes are arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can watch expressions and propagate events.

简单说$scope用来做interpolation。

angular.module('scopeExample', [])
.controller('MyController', ['$scope', function($scope) {
$scope.username = 'World';
$scope.sayHello = function() {
$scope.greeting = 'Hello ' + $scope.username + '!';
};
}]);

When AngularJS evaluates {{name}}, it first looks at the scope associated with the given element for the name property. If no such property is found, it searches the parent scope and so on until the root scope is reached. In JavaScript this behavior is known as prototypical inheritance, and child scopes prototypically inherit from their parents.

这里很重要。比如下面的code

<ul>
<li ng-repeat="item in $ctrl.items"
ui-sref="itemList.itemDetail({itemId: $index})">
{{ item.name }}
<ui-view></ui-view>
</li>
</ul>

相应的ui-view用下面的模板。虽然在该ui-view的scope里没有item,但是按着原型链往上寻找,会在上一级的template中找到该属性。

<ul ng-if="itemDetail.id == item.id">
<li>Price: {{ item.price_large | currency }}</li>
<li>Description: {{ item.description }}</li>
</ul>

More

Scope Hierarchies

Where does Scope come from?

  • Each AngularJS application has exactly one root scope, but may have any number of child scopes. The location where the root scope is attached to the DOM is defined by the location of ng-app directive.
  • ng-controller and ng-repeat, create new child scopes and attach the child scope to the corresponding DOM element.
  • Component directives, which are created with the .component() helper always create an isolate scope.

Retrieving Scopes from the DOM.

To examine the scope in the debugger:

  • Right click on the element of interest in your browser and select ‘inspect element’. You should see the browser debugger with the element you clicked on highlighted.
  • The debugger allows you to access the currently selected element in the console as $0 variable.
  • To retrieve the associated scope in console execute: angular.element($0).scope()

The scope() function is only available when $compileProvider.debugInfoEnabled() is true (which is the default).

$scope and controller

In AngularJS, a Controller is defined by a JavaScript constructor function that is used to augment the AngularJS Scope.

Use controllers to:

  • Set up the initial state of the $scope object.
  • Add behavior to the $scope object.

可见controller就是被设计用来操作scope的,

Scopes and controllers interact with each other in the following situations:

  • Controllers use scopes to expose controller methods to templates (see ng-controller).
  • Controllers define methods (behavior) that can mutate the model (properties on the scope).
  • Controllers may register watches on the model. These watches execute immediately after the controller behavior executes.

controller通过inject来得到AngularJS为其创建的Scope实例。

angular.module('scopeExample', [])
.controller('MyController', MyController)
MyController.$inject = ['$scope']
function MyController($scope) {
$scope.username = 'World';
}

$digest

How to setup watchers?

  • $scope.$watch – don’t do this in a controller <==因为Angular已经帮我们设计好了,下面两个途径就是自动的watcher
  • {{ someProp }}
  •  <input … ng-model=”someProp”>

可以用$scope.$$watcherCount, $scope.$$atchers两个内部变量看到该$scope的watchers的状态

$digest vs. $apply

Digest Cycle does not get triggered automatically if events are unaware of Angular
Solution:
•  Call $digest after your custom code
•  Wrap your custom code inside of $apply
•  Find Angular specific service that handles the same functionality, e.g., $timeout

针对这三种情况,给出下面的sample code

$scope.upCounter = function () {
setTimeout(function () {
$scope.counter++;
console.log("Counter incremented!");
$scope.$digest();
}, 2000);
};
$scope.upCounter = function () {
setTimeout(function () {
$scope.$apply(function(){
$scope.counter++;
console.log("Counter incremented!");
})
}, 2000);
};
$scope.upCounter = function () {
$timeout(function () {
$scope.counter++;
console.log("Counter incremented!");
}, 2000);
};

2-way, 1-way, and 1-time binding

%23%20Angular%20JS%20-%20%24scope%0A@%28myblog%29%5Bangular%2C%20javascript%5D%0A%0A%0A%23%23%20%24scope%0A%3EScope%20is%20an%20object%20that%20refers%20to%20the%20application%20model.%20It%20is%20an%20execution%20context%20for%20expressions.%20Scopes%20are%20arranged%20in%20hierarchical%20structure%20which%20mimic%20the%20DOM%20structure%20of%20the%20application.%20Scopes%20can%20watch%20expressions%20and%20propagate%20events.%0A%0A%u7B80%u5355%u8BF4%24scope%u7528%u6765%u505Ainterpolation%u3002%0A%0A%60%60%60%0Aangular.module%28%27scopeExample%27%2C%20%5B%5D%29%0A.controller%28%27MyController%27%2C%20%5B%27%24scope%27%2C%20function%28%24scope%29%20%7B%0A%20%20%24scope.username%20%3D%20%27World%27%3B%0A%0A%20%20%24scope.sayHello%20%3D%20function%28%29%20%7B%0A%20%20%20%20%24scope.greeting%20%3D%20%27Hello%20%27%20+%20%24scope.username%20+%20%27%21%27%3B%0A%20%20%7D%3B%0A%7D%5D%29%3B%0A%60%60%60%0A%3EWhen%20AngularJS%20evaluates%20%7B%7Bname%7D%7D%2C%20it%20first%20looks%20at%20the%20scope%20associated%20with%20the%20given%20element%20for%20the%20name%20property.%20**If%20no%20such%20property%20is%20found%2C%20it%20searches%20the%20parent%20scope%20and%20so%20on%20until%20the%20root%20scope%20is%20reached.**%20In%20JavaScript%20this%20behavior%20is%20known%20as%20prototypical%20inheritance%2C%20and%20child%20scopes%20prototypically%20inherit%20from%20their%20parents.%0A%0A%u8FD9%u91CC%u5F88%u91CD%u8981%u3002%u6BD4%u5982%u4E0B%u9762%u7684code%0A%60%60%60%0A%3Cul%3E%0A%20%20%20%20%3Cli%20ng-repeat%3D%22item%20in%20%24ctrl.items%22%0A%20%20%20%20%20%20%20%20ui-sref%3D%22itemList.itemDetail%28%7BitemId%3A%20%24index%7D%29%22%3E%0A%20%20%20%20%20%20%20%20%7B%7B%20item.name%20%7D%7D%0A%20%20%20%20%20%20%20%20%3Cui-view%3E%3C/ui-view%3E%0A%20%20%20%20%3C/li%3E%0A%3C/ul%3E%0A%60%60%60%0A%u76F8%u5E94%u7684ui-view%u7528%u4E0B%u9762%u7684%u6A21%u677F%u3002%u867D%u7136%u5728%u8BE5ui-view%u7684scope%u91CC%u6CA1%u6709item%uFF0C%u4F46%u662F%u6309%u7740%u539F%u578B%u94FE%u5F80%u4E0A%u5BFB%u627E%uFF0C%u4F1A%u5728%u4E0A%u4E00%u7EA7%u7684template%u4E2D%u627E%u5230%u8BE5%u5C5E%u6027%u3002%0A%60%60%60%0A%3Cul%20ng-if%3D%22itemDetail.id%20%3D%3D%20item.id%22%3E%0A%20%20%20%20%3Cli%3EPrice%3A%20%7B%7B%20item.price_large%20%7C%20%20currency%20%7D%7D%3C/li%3E%0A%20%20%20%20%3Cli%3EDescription%3A%20%7B%7B%20item.description%20%7D%7D%3C/li%3E%0A%3C/ul%3E%0A%60%60%60%0A%0A%23%23%23%20More%0A%23%23%23%23%20Scope%20Hierarchies%0A**Where%20does%20Scope%20come%20from%3F**%0A-%20Each%20AngularJS%20application%20has%20exactly%20one%20root%20scope%2C%20but%20may%20have%20any%20number%20of%20child%20scopes.%20The%20location%20where%20the%20root%20scope%20is%20attached%20to%20the%20DOM%20is%20defined%20by%20the%20location%20of%20ng-app%20directive.%0A-%20ng-controller%20and%20ng-repeat%2C%20create%20new%20child%20scopes%20and%20attach%20the%20child%20scope%20to%20the%20corresponding%20DOM%20element.%20%0A-%20Component%20directives%2C%20which%20are%20created%20with%20the%20.component%28%29%20helper%20always%20create%20an%20isolate%20scope.%0A%0A%23%23%23%23%20Retrieving%20Scopes%20from%20the%20DOM.%0A%3E%20To%20examine%20the%20scope%20in%20the%20debugger%3A%0A-%20Right%20click%20on%20the%20element%20of%20interest%20in%20your%20browser%20and%20select%20%27inspect%20element%27.%20You%20should%20see%20the%20browser%20debugger%20with%20the%20element%20you%20clicked%20on%20highlighted.%0A-%20The%20debugger%20allows%20you%20to%20access%20the%20currently%20selected%20element%20in%20the%20console%20as%20%240%20variable.%0A-%20To%20retrieve%20the%20associated%20scope%20in%20console%20execute%3A%20angular.element%28%240%29.scope%28%29%0A%0A*The%20scope%28%29%20function%20is%20only%20available%20when%20%24compileProvider.debugInfoEnabled%28%29%20is%20true%20%28which%20is%20the%20default%29.*%0A%0A%23%23%23%23%20%24scope%20and%20controller%0A%3EIn%20AngularJS%2C%20a%20Controller%20is%20defined%20by%20a%20JavaScript%20constructor%20function%20that%20is%20used%20to%20augment%20the%20AngularJS%20Scope.%0A%3E%0A%3EUse%20controllers%20to%3A%0A%3E-%20Set%20up%20the%20initial%20state%20of%20the%20%24scope%20object.%0A%3E-%20Add%20behavior%20to%20the%20%24scope%20object.%0A%0A%u53EF%u89C1controller%u5C31%u662F%u88AB%u8BBE%u8BA1%u7528%u6765%u64CD%u4F5Cscope%u7684%uFF0C%0A%0A%3EScopes%20and%20controllers%20interact%20with%20each%20other%20in%20the%20following%20situations%3A%0A-%20Controllers%20use%20scopes%20to%20expose%20controller%20methods%20to%20templates%20%28see%20ng-controller%29.%0A-%20Controllers%20define%20methods%20%28behavior%29%20that%20can%20mutate%20the%20model%20%28properties%20on%20the%20scope%29.%0A-%20Controllers%20may%20register%20watches%20on%20the%20model.%20These%20watches%20execute%20immediately%20after%20the%20controller%20behavior%20executes.%0A%0Acontroller%u901A%u8FC7inject%u6765%u5F97%u5230AngularJS%u4E3A%u5176%u521B%u5EFA%u7684Scope%u5B9E%u4F8B%u3002%0A%60%60%60%0Aangular.module%28%27scopeExample%27%2C%20%5B%5D%29%0A.controller%28%27MyController%27%2C%20MyController%29%0AMyController.%24inject%20%3D%20%5B%27%24scope%27%5D%0Afunction%20MyController%28%24scope%29%20%7B%0A%20%20%24scope.username%20%3D%20%27World%27%3B%0A%7D%0A%60%60%60%0A%0A%23%23%20%24digest%0A%21%5BAlt%20text%5D%28./1503646988756.png%29%0A%u4E0A%u56FE%u7684%u610F%u601D%u662F%uFF0C%u5982%u679C%u7528JavaScript%u6807%u51C6%u7684onclick%u6765%u6807%u660Ebutton%20handler%uFF0C%u5219Angular%u5E76%u4E0D%u4F1A%u6FC0%u6D3Bdigest%20loop%u3002%u4F46%u662F%u5982%u679C%u7528%u4E86ng-click%2C%20ng-keyup%u6216%u8005%u662Fng-model%u6765%u7ED1%u5B9A%u6570%u636E%uFF0C%u5219%u4F1A%u5728%u53D1%u751F%u76F8%u5E94%u7684%u4E8B%u4EF6%u65F6%uFF0C%u6FC0%u53D1digest%20loop%u3002digest%20loop%u4F1A%u68C0%u6D4B%u6240%u6709%u7684watcher%u6709%u6CA1%u6709%u53D8%u5316%uFF0C%u5982%u679C%u6709%u53D8%u5316%u5219%u4F1A%u505A%u76F8%u5E94%u7684%u66F4%u65B0%28%u4F8B%u5982%uFF1A%u66F4%u65B0HTML%u4E2D%u7684%7B%7B...%7D%7D%uFF0C%u6216%u8005%u66F4%u65B0controller%u4E2D%u7684%u53D8%u91CF%28ng-model%29%29%u3002%0A%0A%23%23%23%20How%20to%20setup%20watchers%3F%0A%3E*%20%5C%24scope.%5C%24watch%20%u2013%20don%u2019t%20do%20this%20in%20a%20controller%20%3C%3D%3D%u56E0%u4E3AAngular%u5DF2%u7ECF%u5E2E%u6211%u4EEC%u8BBE%u8BA1%u597D%u4E86%uFF0C%u4E0B%u9762%u4E24%u4E2A%u9014%u5F84%u5C31%u662F%u81EA%u52A8%u7684watcher%0A%3E*%20%7B%7B%20someProp%20%7D%7D%0A%3E*%20%u202F%26lt%3Binput%20%u2026%20ng-model%3D%22someProp%22%3E%0A%0A%u53EF%u4EE5%u7528%5C%24scope.%5C%24%5C%24watcherCount%2C%20%5C%24scope.%5C%24%5C%24atchers%u4E24%u4E2A%u5185%u90E8%u53D8%u91CF%u770B%u5230%u8BE5%24scope%u7684watchers%u7684%u72B6%u6001%0A%0A%23%23%23%20%5C%24digest%20vs.%20%5C%24apply%0A%3EDigest%20Cycle%20does%20not%20get%20triggered%20automatically%20if%20events%20are%20unaware%20of%20Angular%0ASolution%3A%0A%u2022%u202F%20Call%20%5C%24digest%20after%20your%20custom%20code%0A%u2022%u202F%20Wrap%20your%20custom%20code%20inside%20of%20%5C%24apply%0A%u2022%u202F%20Find%20Angular%20specific%20service%20that%20handles%20the%20same%20functionality%2C%20e.g.%2C%20%24timeout%0A%0A%u9488%u5BF9%u8FD9%u4E09%u79CD%u60C5%u51B5%uFF0C%u7ED9%u51FA%u4E0B%u9762%u7684sample%20code%0A%60%60%60%0A%24scope.upCounter%20%3D%20function%20%28%29%20%7B%0A%20%20setTimeout%28function%20%28%29%20%7B%0A%20%20%20%20%24scope.counter++%3B%0A%20%20%20%20console.log%28%22Counter%20incremented%21%22%29%3B%0A%20%20%20%20%24scope.%24digest%28%29%3B%0A%20%20%7D%2C%202000%29%3B%0A%7D%3B%0A%60%60%60%0A%0A%60%60%60%0A%24scope.upCounter%20%3D%20function%20%28%29%20%7B%0A%20%20setTimeout%28function%20%28%29%20%7B%0A%20%20%20%20%24scope.%24apply%28function%28%29%7B%0A%20%20%20%20%20%20%24scope.counter++%3B%0A%20%20%20%20%20%20console.log%28%22Counter%20incremented%21%22%29%3B%0A%20%20%20%20%7D%29%0A%20%20%7D%2C%202000%29%3B%0A%7D%3B%0A%60%60%60%0A%0A%60%60%60%0A%24scope.upCounter%20%3D%20function%20%28%29%20%7B%0A%20%20%24timeout%28function%20%28%29%20%7B%0A%20%20%20%20%24scope.counter++%3B%0A%20%20%20%20console.log%28%22Counter%20incremented%21%22%29%3B%0A%20%20%7D%2C%202000%29%3B%0A%7D%3B%0A%60%60%60%0A%0A%23%23%202-way%2C%201-way%2C%20and%201-time%20binding%0A%21%5BAlt%20text%7C700x0%5D%28./1503653325764.png%29%0A