-
Notifications
You must be signed in to change notification settings - Fork 14
/
06s-reactivity.md.erb
107 lines (76 loc) · 6.75 KB
/
06s-reactivity.md.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
---
title: Reatividade
slug: reactivity
date: 0006/01/02
number: 6.5
sidebar: true
contents: Aprende sobre o sistema de dependência de código reativo no Meteor.|Entenda as motivações e como isso faz um código declarativo.|Aprenda a usar código avançado que usa dados reativos.
paragraphs: 20
---
Se as coleções são as ferramentas centrais do Meteor, então *reatividade* é a crosta que faz o centro útil.
Coleções transformam radicalmente a forma como seu aplicativo lida com mudanças na informação. Ao invés de ter de checar por mudanças na informação manualmente (vulgo através de chamadas AJAX) e então costurar essas mudanças no HTML, mudanças na informação podem então vir a qualquer momento e serem aplicadas à interface do usuário sem problemas.
Tome um momento para pensar nisso direito: por trás das cortinas, o Meteor é capaz de mudar *qualquer* parte da interface do usuário quando uma coleção subjacente é atualizada.
A forma *imperativa* para se fazer isso seria usar `.observe()`, uma função cursor que dispara callbacks quando documentos correspondentes ao cursor mudam. Nós então poderíamos fazer mudanças ao DOM (o HTML renderizado da nossa página web) através desses callbacks. O código resultante se pareceria com algo assim:
~~~js
Posts.find().observe({
added: function(post) {
// when 'added' callback fires, add HTML element
$('ul').append('<li id="' + post._id + '">' + post.title + '</li>');
},
changed: function(post) {
// when 'changed' callback fires, modify HTML element's text
$('ul li#' + post._id).text(post.title);
},
removed: function(post) {
// when 'removed' callback fires, remove HTML element
$('ul li#' + post._id).remove();
}
});
~~~
Você já pode provavelmente perceber como tal código ficará complexo bem rapidamente. Imagine lidar com mudanças em *cada atributo* da postagem, e ter de fazer mudanças complexas ao HTML dentro dos `<li>` da postagem. Sem mencionar em todos os casos fronteiriços que podem surgir quando nós começamos a precisar de múltiplas fontes de informação que todas podem mudar em tempo real.
<% note do %>
### Quando *devemos* Usar `observe()`?
Usar o padrão acima é às vezes necessário, especialmente quando se lida com widgets de terceiros. Por exemplo, vamos imaginar que nós queremos adicionar e remover alfinetes de um mapa em tempo real baseado em informação de uma Coleção (digamos, para mostrar as localizações dos usuários logados agora).
Em tais casos, você precisará fazer callbacks do `observe()` para fazer o mapa "conversar" com a coleção do Meteor e como reagir às mudanças da informação. Por exemplo, você precisaria dos callbacks `added` e `removed` para chamar os métodos `dropPin()` ou `removePin()` da API do mapa.
<% end %>
### Um approach declarativo
O Meteor provê a nós uma forma melhor: reatividade, a qual é em sumo um approach **declarativo**. Sendo declarativo ele nos permite definir a relação entre objetos uma vez e saber que eles permaneceram em sincronia, ao invés de ter de especificar comportamentos para cada possível mudança.
Este é um conceito poderoso, porque um sistema em tempo real tem muitos inputs que podem todos mudar em momentos imprevisíveis. Ao afirmar declarativamente como nós renderizamos HTML baseado em qualquer fonte de informação reativa com que nos importamos, Meteor pode tomar conta do serviço de monitorar essas fontes e transparentemente cuidar do trabalho bagunçado de manter a interface do usuário atualizada.
Tudo isso para dizer que ao invés de pensar sobre callbacks do `observe`, o Meteor deixa a gente escrever:
~~~html
<template name="postsList">
<ul>
{{#each posts}}
<li>{{title}}</li>
{{/each}}
</ul>
</template>
~~~
E então pega nossa lista de postagens com:
~~~js
Template.postsList.helpers({
posts: function() {
return Posts.find();
}
});
~~~
Por trás das cortinas, o Meteor está armando callbacks do `observe()` para nós, e re-desenhando seguimentos relevantes de HTML quando a informação reativa muda.
### Monitoramento de Dependências em Meteor: Computações
Apesar do Meteor ser um framework reativo, em tempo real, nem *todo* código dentro de um aplicativo em Meteor é reativo. Se este fosse o caso, todo seu aplicativo rodaria de novo cada vez que qualquer coisa mudasse. Então, a reatividade é limitada a áreas específicas do seu código, e nós podemos chamar essas áreas de **computações**.
Em outras palavras, a computação é um bloco de código que roda cada vez que uma das fontes de informação reativa na qual ela depende muda. Se você tem uma fonte de informação reativa (por exemplo, uma variável de Sessão) e gostaria de responder reativamente a ela, você precisará configurar uma computação para tanto.
Note que você geralmente não precisa fazer isso explicitamente porque o Meteor dá às renderizações de cada template sua própria computação (o que significa dizer que o código nos ajudantes de template e callbacks são reativos por padrão).
Cada fonte de informação reativa monitora todas as computações que a estão usando para que poder informá-las quando seu próprio valor mudar. Para tanto, ela chama a função `invalidate()` na computação.
Computações são geralmente configuradas a simplesmente re-avaliar seus conteúdos on invalidation, e isto é o que ocorre nas computações do template (apesar que as computações do template também fazem alguma mágica ao tentar renderizar a página o mais eficientemente). Apesar que você pode ter mais controle quanto ao que cada computação faz on invalidation se você precisar, na prático isto não será algo que vocé fará com freqüência.
### Configurando uma Computação
Agora que nós entendemos a teoria por trás das computações, configurar uma de fato parecerá desproporcionalmente fácil. Nós simplesmente usamos a função `Deps.autorun` para envolver um bloco de código na computação e fazê-lo reativo:
~~~js
Deps.autorun(function() {
console.log('There are ' + Posts.find().count() + ' posts');
});
~~~
Por trás das cortinas, `autorun` cria uma computação, e a configura para re-avaliar quando as fontes de informação na qual ela depende mudam. Nós configuramos uma computação bem simples que simplesmente informa o número de postagens para o console. Já que `Posts.find()` é uma fonte de informação reativa, ela tomará conta de informar a computação para re-avaliar cada vez que o número de postagens mudar.
~~~js
> Posts.insert({title: 'New Post'});
There are 4 posts.
~~~
O resultado em rede de tudo isso é que nós podemos escrever código que usa informação reativa de uma forma bem natural, sabendo que por trás das cortinas o sistema de dependência toma conta de rodar novamente bem na hora certa.