Rumah > Soal Jawab > teks badan
Saya mempunyai kesan vuejs yang pelik, apabila saya menambah data objek baharu, v-for memaparkan semula semua objek, walaupun ia telah diberikan.
Saya sedang melaksanakan tatal tak terhingga seperti buku muka.
Untuk menerangkan kod ini, saya mendapat data baharu daripada firebase dan kemudian menolaknya ke objek data apabila ia mencapai bahagian bawah skrin
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>
Lihat rakaman skrin ini, tetikus fokus, ia sangat lembap, saya tidak boleh klik pada butang semasa vuejs menambah dan memuatkan data baharu
Ini adalah kod yang saya gunakan
Saya mengesyaki bahawa setiap kali data baharu ditambahkan, VueJS memaparkan semula semua data, menyebabkan kesan ini. Bagaimana untuk memaksa vueJS tidak memaparkan semula data yang telah diberikan pada skrin?
P粉5671123912023-12-29 16:34:20
Anda mempunyai dua async IIFE yang tidak perlu; yang kedua dalam forEach
amat bermasalah kerana kod tak segerak di dalamnya akan dilaksanakan secara serentak pada setiap lelaran gelung, yang mempunyai kesan berikut:
getDocs()
akan menyala serta-merta pada setiap lelaran gelung, mungkin menghantar spam kepada pelayan (dengan andaian ini melaksanakan permintaan rangkaian). Adakah ini niat anda? Nampaknya anda hanya boleh mendapat maksimum 5 siaran baharu, jadi tidak mengapa. Jangan guna var
;使用 const
或 let
代替。几乎没有充分的理由再使用 var
pun, biarkan ia mati.
Saya tidak boleh mengatakan ini akan meningkatkan prestasi anda dengan ketara, tetapi saya mengesyorkan perubahan berikut (belum diuji):
async handleScroll() { const d = document.documentElement; const offset = d.scrollTop + window.innerHeight; const 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) { // Prevent loading while we load more posts this.isOkaytoLoad = false; try { // Get new posts 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); // Fetch comments of each post. Do this all at once for each post. // TODO: This can probably be optimized into a single query // for all the posts, instead of one query per post. await Promise.all(roomSnapshot.docs.map(async doc => { const postID = doc.id; const q = query(collection(db, 'comments'), where('post_id', '==', postID)); const commentSnapshot = await getDocs(q); doc.commentCount = commentSnapshot.size; })); // Append the new posts to the list this.postList.push(...roomSnapshot.docs); } catch (ex) { // TODO: Handle error } finally { // Wait a bit to re-enable loading setTimeout(() => { this.isOkaytoLoad = true }, 1000); } } }
Pelaksanaan dalam templat :post-content="truncateString(linkify(post.data().post_content))"
意味着 linkify
将在每次重新渲染期间执行。我怀疑 linkify
Mungkin lambat untuk senarai panjang? Bolehkah ia dikira terlebih dahulu untuk setiap jawatan?
Apabila komponen dipasang, anda sedang mendaftar pendengar acara tatal tetingkap. Jika komponen dimusnahkan, anda perlu menyahdaftar pendengar acara, jika tidak, ia masih akan menyala setiap kali tetingkap ditatal. Ini mungkin tidak menjadi masalah dalam kes anda, tetapi untuk komponen boleh guna semula adalah perlu.