Я работал над приложением, в котором я хотел добавить простую анимацию к элементу списка при щелчке, а также применить некоторый закулисный код, добавляющий этот элемент в группу в Firestore.
Я думал о том, чтобы переключить класс в элементе списка, а затем анимировать элемент, как это (обратите внимание, я использую Angular, но эта статья применима ко всем фреймворкам):
onClickItem(): void { item.isActive = true; } animations: [ trigger("isActive", [ state("true", style({ backgroundColor: "#08aeea", color: "#fff" })), transition("* => true", animate("150ms ease-in")) ]) ]
Сладкий, хорошо, слишком просто. Я пробую это в своем списке, и вуаля работает как волшебство, затем я заметил что-то забавное, иногда я нажимал на элемент списка, и анимация наполовину запускалась, мигала и возвращалась в нормальное состояние - что происходит ???
Не собираюсь лгать, это озадачило меня примерно на час. Затем я посмотрел, как рендерил свой список из Firestore:
this.groups$ = this.getGroupsAsObservable(); // groups$ to indicate is an Observable getGroupsAsObservable(): Observable<Group[]> { return this.afs.collection<Group>("groups").valueChanges(); }
Обратите внимание на часть valueChanges () - это секретный соус, который позволяет вашему приложению передавать данные из firestore в реальном времени.
Теперь происходило то, что при нажатии на элемент за кулисами он проверял, принадлежит ли этот элемент группе, и, если нет, добавлял элемент в группу, а также небольшой фрагмент данных, в котором перечислялись связанные элементы для та группа (объект) в Firestore.
Это означало, что документ группы изменился и вызовет повторную визуализацию в нашем приложении!
Здесь я понял, что мне нужно, чтобы список моих групп был чисто статическим.
На самом деле это было довольно сложно, нигде в документации не упоминаются «статические» или «однократно прочитанные» данные.
Первое, что мне нужно было для данных, - это вернуть снимок данных. В документации было немного об этом:
getUsersGroupsOnce(userId): Promise<QuerySnapshot> { // return a static snapshot of the users groups return this.afs.collection("groups", ref => ref.where(`users.${userId}`, "==", true) ) .ref.get(); // this is the static part }
Милая, теперь у меня есть статическая ссылка - мне нужно построить для этого массив, следуя документам, которые я сделал:
this.fb.getUsersGroupsOnce(user.uid).then(q => { q.forEach(doc => { console.log(doc.data()) }); });
Хорошо, теперь у меня есть данные, которые мне просто нужно отправить в массив, верно? Я пробовал это:
q.forEach(doc => { this.groups.push(doc.data()); });
Но машинописный текст жаловался, поэтому я как бы заставил это сделать так:
q.forEach(doc => { this.groups.push(doc.data() as Group); });
И вуаля, теперь у меня есть статический список - или, как я люблю его называть, «прочитал один раз». Теперь я знаю, что потоки данных в реальном времени 99/100 - это здорово, но полезно знать, как время от времени получать статические данные.
Есть способ лучше? Не стесняйтесь оставлять комментарии ниже.