-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy path06s-reactivity.md.erb
111 lines (79 loc) · 10.5 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
108
109
110
111
---
title: Реактивність
slug: reactivity
date: 0006/01/02
number: 6.5
sidebar: true
contents: Ознайомитесь з реактивною системою залежностей коду Meteor.|Зрозумієте мотивації і як вони роблять код декларативним.|Навчитесь використовувати код, що оперує з реактивними даними.
paragraphs: 21
---
Якщо колекції - це ядерна фіча Метеору, то *реактивність* - це оболонка, яка робить це ядро корисним.
Колекції радикально змінюють спосіб взаємодії вашого додатку зі змінами данних. Замість необхідності перевіряти зміну даних вручну (наприклад, через AJAX-виклик) і далі патчити ці зміни у ваш HTML, замість цього зміни даних приходять у будь-який час і застосовуються до вашого інтерфейсу користувача Метеору.
Задумайтесь на хвильку: за лаштунками Метеор здатний змінити *будь-яку* частину вашого інтерфейсу, коли відповідна колекція змінюється.
*Імперативний* шлях зробити те ж саме - це використати `.observe()`, курсор функцію, що запускає колбеки, коли документи відповідають змінам курсору. Ми змогли б застосувати зміни для DOM (відрендеренний HTML нашої сторінки) через ці колбеки. Результуючий код виглядав би так:
~~~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();
}
});
~~~
Ви можливо вже бачите як такий код вже скоро стане досить складним. Уявіть оперування зі змінами до *кожного атрибуту* посту і зміна складного HTML-коду посту всередині тегу `<li>`. Не беручи до уваги складні випадкі, що можуть з’явитись, коли ми починаємо опиратись на різні ресурси інформацію, що можуть змінюватись в реальному часі.
<% note do %>
### Коли нам *слід використовувати* `observe()`?
Використання вищенаведенного патерну інколи необхідно, особливо, коли працюємо з віджетами третіх сторін. Наприклад, уявіть, що нам теба додати або забрати піни на карті в реальному часі базуючись на даних Колекції (наприклад, показати локації авторизованих тільки що користувачів).
У таких випадках, вам треба використовувати `observe()` колбеки з метою отримання карти "розмови" з колекцією Метеор і знати як реагувати на зміну даних. Наприклад, вам слід спиратись на `добавлені` і `видалені` колбеки для виклику власних методів API карти: `dropPin()` або `removePin()`.
<% end %>
### Декларативний підхід
Метеор надає нам змогу кращого підходу: реактивність з ядром у вигляді **декларативного** підгоду. Виходячи з декларативності дозволяє нам визначати зв’язки між об’єктами і знати, що вони знаходяться в синхронізації, замість необхідності визначати поведінку для всіх можливих змін.
Це потужна концепція, тому що система реального часу має багато ввідних, що можуть змінюватись в непрогнозовані проміжки часу. Декларативність визначає яким чином ми рендеримо HTML базуючись на яких реактивних джерел данних, Метеор подбає про моніторинг цих джерел і прозоро зробить цю складну роботу по підтриманні інтерфейсу в належному стані по відношенню до часу.
All this to say that instead of thinking about `observe` callbacks, Meteor lets us write:
~~~html
<template name="postsList">
<ul>
{{#each posts}}
<li>{{title}}</li>
{{/each}}
</ul>
</template>
~~~
І тоді отримаємо список наших постів за допомогою:
~~~js
Template.postsList.helpers({
posts: function() {
return Posts.find();
}
});
~~~
За лаштунками Метеор прив’язує колбеки `observe()` для нас і перемальовує відповідні секції HTML, коли змінюються реактивні дані.
### Відслідковування залежностей в Meteor: розрахунки
Не дивлячись на те, що Meteor - це реактивний фреймворк реального часу, не *весь* код всередині Метеор додатку є реактивним. Якщо це саме той випадок, то весь додаток перезавантажувся кожен раз, коли щось змінюється. Замість цього, реактивність обмежена у специфічних зонах вашого коду і ми називаємо ці зони **розрахунками**.
Іншими словами, розрахунок - це блок коду, що запускається кожен раз, коли одне з джерел реактивних даних змінюється, він залежить від змін. Якщо ви маєте джерело реактивних даних (наприклад, змінну сесії) і хотіли б реактивно реагувати на неї, то вам необхідно встановити розрахунок для неї.
Зверніть увагу, що звичайно вам не треба цього робити, тому що Meteor вже надав кожному шаблону таку можливість, він рендерить свій власний спеціальний розрахунок (що значить, що код в хелперах шаблону і колбеках реактивний за замовчуванням).
Кожне реактивне джерело даних відслідковує всі розрахунки, що використовують її, таким чином, щоб вона давала знати їм кожен раз коли її значення змінюються. Щоб це зробити вона викликає функцію `invalidate()` для розрахунку.
Розрахунки звичайно встановлюються для простого переоцінення свого змісту при інвалідації і це відбувається з розрахунками шаблону (хоча розрахунки шаблону також роблять деяку магію для більш ефективного перемалювання сторінки). Також ви можете мати більше контролю на тим, як ваші розрахунки працюють над необхідною інвалідацією, на практиці це завжди поведінка, яку ви будете використовувати.
### Налаштування розрахунку
Тепер, коли ви зрозуміли теорію щодо розрахунків, реальна настройка одного буде досить простою. Ми просто використаємо функцію `Tracker.autorun` для включення блоку коду в розрахунок і зробимо його реактивним:
~~~js
Meteor.startup(function() {
Tracker.autorun(function() {
console.log('There are ' + Posts.find().count() + ' posts');
});
});
~~~
Зверніть увагу, що нам необхідно обгорнути блок `Tracker` всередину блока `Meteor.startup()` для того, щоб він запускався лише, коли Meteor закінчить завантаження колекції `Posts`.
За лаштунками, `autorun` далі створює розрахунок і прив’язує його до переоцінки залежного джерела даних. Ми встановили дуже простий розрахунок, що просто веде лог кількості постів в консолі. Оскільки `Posts.find()` - це реактивне джерело данних, воно подбає про повідомлення розрахунку про обчислення кожного разу при зміні кількості постів.
~~~js
> Posts.insert({title: 'New Post'});
There are 4 posts.
~~~
Практичним результатом всього цього буде те, що ми можемо писати код, що використовує реактивні дані, в дуже природний спосіб, знаючи, що за лаштунками система залежностей подбає про перезапуск всього в потрібний момент.