J'ai un effet vuejs étrange, lorsque j'ajoute de nouvelles données d'objet, v-for restitue tous les objets, même s'ils ont déjà été rendus.
J'implémente le défilement infini comme Facebook.
Pour expliquer ce code, je récupère de nouvelles données de Firebase, puis je les transmets dans un objet de données lorsqu'elles atteignent le bas de l'écran
var vueApp = new Vue({ el: '#root', data: { postList: [], isOkaytoLoad: false, isRoomPostEmpty: false, }, mounted: function() { // Everytime user scroll, call handleScroll() method window.addEventLis tener('scroll', this.handleScroll); }, methods: { handleScroll: function() { var d = document.documentElement; var offset = d.scrollTop + window.innerHeight; var height = d.offsetHeight - 200; // If the user is near the bottom and it's okay to load new data, get new data from firebase if (this.isOkaytoLoad && offset >= height) { this.isOkaytoLoad = false; (async()=>{ const lastPost = this.postList[this.postList.length - 1]; const room_id = PARAMETERS.get('room'); const q = query(collection(db, 'posts'), where('room', '==', room_id), orderBy("time", "desc"), limit(5), startAfter(lastPost)); const roomSnapshot = await getDocs(q); roomSnapshot.forEach((doc) => { const postID = doc.id; (async()=>{ // Put the new data at the postList object this.postList = [...this.postList, doc]; const q = query(collection(db, 'comments'), where('post_id', '==', postID)); const commentSnapshot = await getDocs(q); doc['commentCount'] = commentSnapshot.size; //this.postList.push(doc); console.log(this.postList); setTimeout(()=>{ this.isOkaytoLoad = true }, 1000); })(); }); })(); } } } })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div v-if="postList.length > 0" class="card-containers"> <!-- I have a component `Postcard` in my js file and it works well --> <Postcard v-for="post in postList" :key="post.id" :post-id="post.id" :owner-name="post.data().owner_displayName" :owner-uid="post.data().owner_id" :post-type="post.data().post_type" :image-url="post.data().image_url" :post-content="truncateString(linkify(post.data().post_content))" :room="post.data().room" :time="post.data().time.toDate()" :likers="post.data().likers" :comment-count="post.commentCount" :file-url="post.data().file_url" :file-name="post.data().file_name" :downloads="post.data().downloads"> </Postcard> </div>
Regardez cet enregistrement d'écran, souris focalisée, c'est tellement lent, je ne peux même pas cliquer sur les boutons pendant que vuejs ajoute et charge de nouvelles données
C'est le code que j'utilise
Je soupçonne qu'à chaque fois que de nouvelles données sont ajoutées, VueJS restitue toutes les données, provoquant cet effet. Comment forcer vueJS à ne pas restituer les données déjà restituées à l'écran ?
Vous avez deux IIFE asynchrones inutiles ; le second dans
forEach
est particulièrement problématique car le code asynchrone qu'il contient sera exécuté simultanément à chaque itération de boucle, ce qui a les effets suivants :getDocs()
se déclenchera immédiatement à chaque itération de boucle, envoyant éventuellement du spam au serveur (en supposant qu'il s'agit d'une requête réseau). Est-ce votre intention ? Il semble que vous ne puissiez recevoir qu'un maximum de 5 nouveaux messages, donc c'est probablement bien.N’utilisez pas
var
;使用const
或let
代替。几乎没有充分的理由再使用var
non plus, laissez-le mourir.Je ne peux pas dire que cela améliorera significativement vos performances, mais je recommande les changements suivants (non testés) :
Exécution dans le modèle
:post-content="truncateString(linkify(post.data().post_content))"
意味着linkify
将在每次重新渲染期间执行。我怀疑linkify
Peut-être lente pour les longues listes ? Peut-il être pré-calculé pour chaque poste à l’avance ?Lorsque le composant est installé, vous enregistrez un écouteur d'événement de défilement de fenêtre. Si le composant est détruit, vous devez désenregistrer l'écouteur d'événements, sinon il se déclenchera toujours à chaque défilement de la fenêtre. Cela ne pose peut-être pas de problème dans votre cas, mais pour les composants réutilisables, c'est nécessaire.