Вы находитесь на странице: 1из 9

Hi there!

Ive prepared this short guide to help


people get a deeper understanding of core
Angular concepts. It answers three questions:
1. Why Learn to Think with Angular?
2. Does Angular Have a Philosophy?
3. How Do I Think with Angular?

Lets get started!
David Graunke,
david@thomasstreet.net
Thomas STREET
Thinking
with Angular
Why Learn to Think with Angular?
Programming with Angular can be very
different from programming with plain Javascript,
jQuery, or even frameworks like Backbone. Angular
offers so much to developers, but requires a
slightly new way of thinking in return.
If you learn to think like Angular, youll not only
be faster and more effective when using built-in
Angular tools, but your own code will be simpler,
more expressive, and more direct.
Does Angular have a Philosophy?
I think it does. I would say its create
declarative bindings between state and view.
Lets unpack that a little. First, some
denitions.
By state I mean all the data youre storing in
memory to support the app in the case of a
todo-list app, it includes domain data like user
objects and todo-list items. It also includes
application-specic state like the current active
page, and whether a given modal or drawer is
activated.
Thinking with Angular - 2
Now, you can use the view to store state for
example, if the only way to know how many todo
tasks a user has is by the return value of
$(.todos).children().length, then youre storing
state in the view. Hopefully youre not doing that,
and state is instead stored in Javascript objects in
memory.
By view I mean the state of the document
visible to the user the DOM.
Now how about declarative bindings what
does that mean? By declarative, I mostly mean
not imperative. Imperative code is a sequence of
instructions that change the execution state of the
application. Heres an example of imperative code
for creating a view (i.e., modifying the DOM) for our
example todo-list app:
for (var i = 0; i < todos.length; i++) {
var el = $(<li>);
el.innerHTML = todos[i].value;
$(.todos).append(el);
}
This code is imperative because we have a
sequence of instructions that each create and
mutate objects, and manually modify the DOM. We
Thinking with Angular - 3
create a new <li> html element and assign it to the
variable el, we mutate (update) a eld on el, and
we insert it into the DOM. Each step changes the
execution context.
Lets look at the Angular equivalent of that code:
<li ng-repeat=todo in todos>{{todo.value}}</li>
Whats going on here? Weve taken a <li>
HTML element and added a custom attribute
ng-repeat. By adding that attribute, were telling the
Angular template compiler that we always want
one <li> element for each todo in our todo list.
Weve also put a reference to the todo for that <li>
in curly-brackets between the tags. That tells the
Angular compiler that we want to bind that chunk
of the DOM to the value of the todo.
That brings us to our last denition: bindings.
In this context, were contrasting binding with
assignment. Assignment is saying el.innerHTML =
todos[i].value its a one-time operation that
copies the contents of todos[i].value and puts it in
el.innerHTML. Its an imperative action that alters
our state. What were calling binding is a
declaration of a relationship between two values.
Thinking with Angular - 4
Angular has one-way bindings that
supercially resemble the imperative assignment
above. However, after we assign el.innerHTML,
updates to todos[i].value dont have any effect on
it. With a one-way binding, that piece of the DOM
will be automatically updated to reect its bound
value. Bindings can also be two-way, which well
talk about in a moment.
In our Angular example above, we have two
bindings. Our rst is ng-repeat, and the second is
{{todo.value}}. I mentioned above that Angular will
create one list item element for each item in todos,
just like our imperative code does. But theres a
difference. In the Angular example, were not just
telling Angular to create a <li> right now were
telling it to bind this chunk of the DOM to the todos
data, making sure that theres always a <li>
element for each item in todos. That means when
we alter todos by doing something like
todos.push({date: new Date(),
value: Write Angular handbook!})
the DOM will automatically be updated!
Now, without Angular, we could certainly track
each time todos changes and then re-trigger our
imperative view-building code. Wed have a
Thinking with Angular - 5
simple (declarative!) model in our heads make
sure I always have one <li> element for each todo,
displaying its content but wed be forced to
translate that simple model into complex data
tracking and DOM manipulation. With Angular,
were able translate our simple mental model into
the application with a minimum of fuss.
The Angular code above gives us an example
of a declarative one-way binding every time
todos changes, the DOM is updated. But Angular
also gives us two-way bindings, where data not
only propagates forward to the DOM, but user
actions propagate data back to the application
state! Lets look at an example:
<script>
ourApp = function($scope) {
$scope.rating = 50;
};
</script>
<body ng-app ng-controller=ourApp>
Rate: <input type=range
ng-model=rating min=0 max=100 /
>
Your rating: {{rating}}
</body>
(You can play with a live version of this here:
http://plnkr.co/edit/MJ1yyh4HvbGIJ9WK1RVh?p=preview)
Thinking with Angular - 6
Here we see an Angular controller the
ourApp is a factory object that creates our data on
our controller, called $scope, which is just an object
we use to hold our state. You also see the attribute
ng-app on the body element, which is a signal to
Angular that everything inside the body should be
compiled as an Angular app.
Play with the linked version of the code
what happens when you scrub the slider back and
forth? The readout of the rating updates. Now, the
readout (following Your rating:) is a simple one-
way binding like we saw before whats
interesting is that were updating the value of
$scope.rating without any event handlers! Instead,
we use the ng-model attribute to bind the value of
the input slider to the value of rating. When the
value of the slider changes, the value of rating
changes, which is reected in the DOM.

If something else in our code (like a message
from the server) updated the value of
$scope.rating, the position of the slider would
change Angular has bound them so theyre
always the same. Rather than wiring up a bunch of
event handlers to keep our data and view in sync,
weve instead used Angular to declare
relationships between values.
Thinking with Angular - 7
Now, Angular is not a purely declarative
framework. Most apps will have a lot of imperative
code modifying the application state code like
our todos.push example above. But using Angular
will save you from hundreds to thousands of lines
of code dedicated to keeping your state and view
and sync and youll be happy to leave that
chore to the library developers.
How Do I Think with Angular?

So, why did I think it was worth exploring the
philosophy behind Angular? When I started with
Angular, I had no trouble creating simple bindings
like our examples above the introductory
documentation is great, and for beginners Angular
can be simple and intuitive. But when trying to
extend Angular by creating new directives, or
trying to integrate third-party libraries I struggled
to create code that went with the grain of Angular.
It took me a while to understand just why
Angular worked the way it did. But when I did, I
was able to create code that captured some of the
philosophy of Angular code that let developers
(including myself!) declare relationships, rather
than writing imperative code.
Thinking with Angular - 8
There are lots of things we didnt touch on here
that will help you write declarative code: custom
directives, Angulars watch system, and the
$ngModel module to name a few. Learning to write
declarative code involved using all of those things.
Heres a list of techniques I learned, which I hope
can be a jumping off point for you as you dive into
building and thinking with Angular:
4. Avoid imperative code that modies the
DOM.
5. Avoid events let Angulars change-watch
system propagate updates.
6. Use directives to hide imperative code for
interacting with third-party libraries. Put the
imperative code they need in compile and
link functions.
7. Use the $ngModel module to create two-
bindings in your custom directives.
I hope this has been helpful! Angular can be
very different from other ways of programming, but
investing in learning to think with Angular, rather
than against Angular, can be a great help.
- David
Thinking with Angular - 9

Вам также может понравиться