Angular scope
In web applications built with angular, the concept of scope is throughout it. Many instructions in the angular view will create a scope, such as ng-app, ng-controller, etc. This scope is $scope (version before angular1.2) we inject when writing controller constructors. It is a concept in the view model. Our data model is defined in scope.
Angular scope pit
People who have used angular should go through a process, that is, when they were a novice at the beginning, they just saw the two-way binding of data.
Scope pit 1 in Angular
No matter how he started using it directly, he would bind it in one go. After binding, if you are lucky (the old bird who understands the principle of angular scope ignores it), then the two-way binding will start working as expected. At this time, we also feel that we are so powerful that we can realize "two-way binding" so quickly, which is a new feature that has not been heard of.
So why is the above saying that two-way binding works properly because of good luck? Because when novices first started learning angular, they just read the tutorial and changed the code to achieve their business needs. Even if there are some players who can learn official documents at the beginning, they are still a minority. Therefore, most of the friends who have just learned angular actually don’t understand the principles, but they think they already know how to use them.
After saying so much, let's take a look at the situation where a novice starts to specify a data model in the scope and bind it in two-way directions. In this case, you will encounter the pitfall mentioned above. Let’s take a look at the code first.
// 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">Increment</button> </div></div>// javascriptfunction OuterCtrl($scope) { $scope.a = 1;}function InnerCtrl() {}The above code is an extremely simple example of two-way binding. After the page is loaded, 1 will be displayed in the external div and the internal div. When the increment button is pressed, you will find that only the internal 1 becomes 2. The same is true for continuing to press, only the internal number will increase. So at this time, novices often panic. What about the magical two-way binding that was agreed upon?
Scope pit 2 in Angular
At this time, the baby was a little emotional. He walked up stackoverflow and the official documents. Finally, he found that there was indeed a solution, such as writing a as the attribute data.a of an object:
// 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">Increment</button> </div></div>// javascriptfunction OuterCtrl($scope) { $scope.data = { a: 1 };}function InnerCtrl() {}Then I found that it could work, and both numbers were incremented. I was the king of two-way binding... and then I threw it aside and continued to learn the next part of the tutorial without caring about the specific principles. This is actually my mental journey when I first learned angular. I was really ashamed to do the application and deploy it to the production environment before I remembered to study the internal principles.
The pit always needs to be filled
I have said so much nonsense and I have stepped on the pit. I have entered the pit filling stage, which means that this pit can be solved by the attributes written as objects. In fact, after knowing the principle, it is easy to understand. The inner and outer scope of angular is inherited by the prototype chain based on JavaScript, and only the prototype chain inheritance method is used. Friends with some JavaScript basics should be able to react instantly. The reference type value in the sub-class prototype object and the reference type value in the parent instance object are the same reference, and the basic type value will overwrite the basic type value in the parent object. This is actually the reason why combination inheritance exists, because just using prototype chain inheritance will bring about the appeal problem, which is a bit far-reaching.
In short, here we can look at the first example as follows:
function OuterCtrl() { this.a = 1;}function InnerCtrl() {}var outer = new OuterCtrl();InnerCtrl.prototype = outer;var inner = new InnerCtrl();inner.a = inner.a + 1; Here, we set the prototype object of the constructor of the internal controller to an external scope object, so that the generated internal scope object inherits the property a in the external object outer. This property is a basic type value. When accessing the property a of the internal object, since the internal object itself does not have such attributes, it will look up from its prototype object. There is such attribute in the prototype object outer, so the return value is no problem, but if we assign value to the property a of the internal scope object, the problem will arise. inner.a = inner.a + 1; This statement actually proceeds the process mentioned above to find the value of the a property, and then assigns the returned value to the a property of the internal scope object. Since the a property does not exist, a basic type value property of a is created, blocking the a property in the outer scope object outer, and this pit comes out.
Therefore, if we replace the basic type value attribute with the reference type value attribute, the problem can be solved, because the corresponding attributes of the two objects are the same reference type value referenced, and no matter where it is modified, it will be reflected on all objects that refer to it.
Summarize
The above is all about the pitfalls that need to be paid attention to in Angular. I hope the content of this article will be helpful to everyone to learn about the scope in Angular.