JesseZhao1990 / blog

learing summary
MIT License
62 stars 7 forks source link

angularjs之scope #169

Open JesseZhao1990 opened 5 years ago

JesseZhao1990 commented 5 years ago

原文:https://code.angularjs.org/1.6.10/docs/guide/scope

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是一个对你的程序model层进行引用的一个对象。它是angular中表达式的一种执行环境。Scope和scope之间是类似于dom和dom之间的层级关系。Scope可以监测 angularjs的表达式和发送事件。

scope的特征

Scopes provide APIs ($watch) to observe model mutations.

Scopes provide APIs ($apply) to propagate any model changes through the system into the view from outside of the "AngularJS realm" (controllers, services, AngularJS event handlers).

Scopes can be nested to limit access to the properties of application components while providing access to shared model properties. Nested scopes are either "child scopes" or "isolate scopes". A "child scope" (prototypically) inherits properties from its parent scope. An "isolate scope" does not. See isolated scopes for more information.

Scopes provide context against which expressions are evaluated. For example {{username}} expression is meaningless, unless it is evaluated against a specific scope which defines the username property.

Scope 是数据模型

Scope is the glue between application controller and the view. During the template linking phase the directives set up $watch expressions on the scope. The $watch allows the directives to be notified of property changes, which allows the directive to render the updated value to the DOM.

Both controllers and directives have reference to the scope, but not to each other. This arrangement isolates the controller from the directive as well as from the DOM. This is an important point since it makes the controllers view agnostic, which greatly improves the testing story of the applications.

scope 是 controller和view的粘合剂。在模板的linking阶段,指令初始化scope上的$watch表达式。当对应的属性变化的时候,$watch 能让指令得到通知。这样指令就可以去渲染更新之后的值。

controllers和指令都有对scope的引用, 但是彼此不引用。这样的安排将controller和指令和DOM隔离开来。这是很重要的一个地方,它使controllers和视图分离,这极大的提高了应用的可测试性。

image

In the above example notice that the MyController assigns World to the username property of the scope. The scope then notifies the input of the assignment, which then renders the input with username pre-filled. This demonstrates how a controller can write data into the scope.

Similarly the controller can assign behavior to scope as seen by the sayHello method, which is invoked when the user clicks on the 'greet' button. The sayHello method can read the username property and create a greeting property. This demonstrates that the properties on scope update automatically when they are bound to HTML input widgets.

在上边的例子中,MyController 给scope上的username属性赋值一个World,scope接着通知assignment的input,接着assignment会使用username去渲染input。这演示了一个controller是怎么想scope写入数据的。

和上边的情况相似,controller也可以给scope指配行为,比如sayHello方法。这个方法在用户点击greet按钮的时候会背触发。sayHello可以读取username的值,并且创建一个greeting属性。这表明scope上的属性可以自动更新,当他们被绑定到HTML上的时候。

Logically the rendering of {{greeting}} involves:

retrieval of the scope associated with DOM node where {{greeting}} is defined in template. In this example this is the same scope as the scope which was passed into MyController. (We will discuss scope hierarchies later.)

Evaluate the greeting expression against the scope retrieved above, and assign the result to the text of the enclosing DOM element.

You can think of the scope and its properties as the data which is used to render the view. The scope is the single source-of-truth for all things view related.

下面是涉及到渲染 {{greeting}} 的执行逻辑:

你可以认为scope以及scope上的属性是作为data,用来渲染view层的。scope是和view相关的所有东西的唯一可信来源。

From a testability point of view, the separation of the controller and the view is desirable, because it allows us to test the behavior without being distracted by the rendering details.

image

从view的可测试性的角度来看,把controller和view分离是非常棒的,因为他能够允许我们去测试页面的行为,而不需要去关注渲染的细节。

scope的层级结构

Each AngularJS application has exactly one root scope, but may have several child scopes.

每个angularjs应用仅仅有一个根scope,但是可能会有几个child scope

The application can have multiple scopes, because some directives create new child scopes (refer to directive documentation to see which directives create new scopes). When new scopes are created, they are added as children of their parent scope. This creates a tree structure which parallels the DOM where they're attached.

应用可以有多个scope,是因为一些指令会创建一个新的child scope,(这里可以参考指令相关的文档来进一步看一下那些指令会创建新的scope。)当新的scope被创建之后,他们作为父scope的孩子被添加。这样就会创建一个类似于他们附带的dom元素一样的树状结构。

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.

当angularjs 计算 {{name}}的时候,它首先会在 name 属性所在的元素对应的scope上查找。如果没有找到,它会继续向父scope上查找,直至根scope。在js中,这种行为叫做原型继承,child scope利用原型加成继承他们的父scope。

This example illustrates scopes in application, and prototypical inheritance of properties. The example is followed by a diagram depicting the scope boundaries.

下面这个例子说明了应用中的scope的原型继承, 这个例子的后边有一个图片,标明了scope的边界。

image

image

Notice that AngularJS automatically places ng-scope class on elements where scopes are attached. The