| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [View Raw Code] [Original HTTPS Page] |
A View is a core primitive used by angular to render the DOM tree. A ViewContainer is location in a View which can accept child Views. Every ViewContainer has an associated ViewContainerRef than can contain any number of child Views. Views form a tree structure which mimics the DOM tree.
Let's examine a simple View and all of its parts in detail.
Assume the following Component:
class Greeter {
greeting:string;
constructor() {
this.greeting = 'Hello';
}
}And assume following HTML View:
<div>
Your name:
<input var="name" type="Text">
<br>
{{greeting}} {{name.value}}!
</div>The above template is compiled by the Compiler to create a ProtoView. The ProtoView is then used to create an instance of the View. The instantiation process involves cloning the above template and locating all of the elements which contain bindings and finally instantiating the Directives associated with the template. (See compilation for more details.)
<div> | viewA(greeter)
Your name: | viewA(greeter)
<input var="name" type="Text"> | viewA(greeter): local variable 'name'
<br> | viewA(greeter)
{{greeting}} {{name.value}}! | viewA(greeter): binding expression 'greeting' & 'name.value'
</div> | viewA(greeter)The resulting View instance looks something like this (simplified pseudo code):
viewA = new View({
template: ...,
context: new Greeter(),
localVars: ['name'],
watchExp: ['greeting', 'name.value']
});Note:
An important part of an application is to be able to change the DOM structure to render data for the user. In Angular this is done by inserting child views into the ViewContainer.
Let's start with a View such as:
<ul>
<li template="ng-for: #person of people">{{person}}</li>
</ul>During the compilation process the Compiler breaks the HTML template into these two ProtoViews:
<li>{{person}}</li> | protoViewB(Locals)and
<ul> | protoViewA(someContext)
<template></template> | protoViewA(someContext): protoViewB
</ul> | protoViewA(someContext)The next step is to compose these two ProtoViews into an actual view which is rendered to the user.
Step 1: Instantiate viewA
<ul> | viewA(someContext)
<template></template> | viewA(someContext): new NgFor(new ViewContainer(protoViewB))
</ul> | viewA(someContext)Step2: Instantiate NgFor directive which will receive the ViewContainerRef. (The ViewContainerRef has a reference to protoViewA).
Step3: As the NgFor directive unrolls it asks the ViewContainerRef to instantiate protoViewB and insert it after the ViewContainer anchor. This is repeated for each person in people. Notice that
<ul> | viewA(someContext)
<template></template> | viewA(someContext): new NgFor(new ViewContainer(protoViewB))
<li>{{person}}</li> | viewB0(locals0(someContext))
<li>{{person}}</li> | viewB1(locals0(someContext))
</ul> | viewA(someContext)Step4: All of the bindings in the child Views are updated. Notice that in the case of NgFor the evaluation context for the viewB0 and viewB1 are locals0 and locals1 respectively. Locals allow the introduction of new local variables visible only within the scope of the View, and delegate any unknown references to the parent context.
<ul> | viewA
<template></template> | viewA: new NgFor(new ViewContainer(protoViewB))
<li>Alice</li> | viewB0
<li>Bob</li> | viewB1
</ul> | viewAEach View can have zero or more ViewContainers. By inserting and removing child Views to and from the ViewContainers, the application can mutate the DOM structure to any desirable state. A View may contain individual nodes or a complex DOM structure. The insertion points for the child Views, known as ViewContainers, contain a DOM element which acts as an anchor. The anchor is either a template or a script element depending on your browser. It is used to identify where the child Views will be inserted.
A View can also contain Components. Components contain Shadow DOM for encapsulating their internal rendering state. Unlike ViewContainers which can contain zero or more Views, the Component always contains exactly one Shadow View.
<div> | viewA
<my-component> | viewA
#SHADOW_ROOT | (encapsulation boundary)
<div> | viewB
encapsulated rendering | viewB
</div> | viewB
</my-component> | viewA
</div> | viewAEach View acts as a context for evaluating its expressions. There are two kinds of contexts:
Let's assume following component:
class Greeter {
greeting:string;
constructor() {
this.greeting = 'Hello';
}
}And assume the following HTML View:
<div> | viewA(greeter)
Your name: | viewA(greeter)
<input var="name" type="Text"> | viewA(greeter)
<br> | viewA(greeter)
{{greeting}} {{name.value}}! | viewA(greeter)
</div> | viewA(greeter)The above UI is built using a single View, and hence a single context greeter. It can be expressed in this pseudo-code.
var greeter = new Greeter();The View contains two bindings:
var greeter = new Locals(new Greeter(), {name: ref_to_input_element })By wrapping the Greeter instance into the Locals we allow the view to introduce variables which are in addition to the Greeter instance. During the resolution of the expressions we first check the locals, and then the Greeter instance.
Views transition through a particular set of states:
| Back | FazBrowse Home | New Git URL |