การแบ่งหน้าอย่างง่ายสำหรับการโหลดเนื้อหาเพิ่มเติมในขณะที่ยังคงฟังการอัปเดต
แรงจูงใจ
การเลื่อนแบบไม่มีที่สิ้นสุดเป็นฟังก์ชันที่ต้องการโดยทั่วไป โดยเฉพาะอย่างยิ่งในฟีดทุกประเภท ต้องมีการโหลดเนื้อหาเพิ่มเติมตามความต้องการในขณะที่ผู้ใช้เลื่อนดู สิ่งนี้อาจทำได้ง่ายเพียงพอหากเนื้อหาเป็นแบบคงที่ คุณเพียงแค่โหลด n
รายการ และเมื่อผู้ใช้เลื่อนไปที่จุดสิ้นสุดของรายการเหล่านั้น คุณจะโหลดเพิ่มอีก n
รายการ ทำซ้ำ. Firebase ให้ตัวอย่างที่ดีของ วิธีการทำสิ่งนี้ (ส่วนที่โหลดนี้ ไม่ใช่การเลื่อน)
แต่ถ้าคุณมีข้อมูลแบบไดนามิก และคุณต้องรับฟังการเปลี่ยนแปลงด้วย สิ่งที่ถูกเพิ่ม ลบ และแก้ไข สิ่งต่างๆ มีความซับซ้อนขึ้นเล็กน้อย และฉันไม่พบบทช่วยสอนหรือตัวอย่างเกี่ยวกับวิธีการทำ ดังนั้นหลังจากที่เข้าใจแล้ว ฉันจึงตัดสินใจสร้างมันขึ้นมา เพื่อความง่าย ฉันจะไม่กล่าวถึงวิธีการทริกเกอร์ (ปุ่ม การเลื่อน ฯลฯ) ฟังก์ชันเพื่อโหลดเนื้อหาเพิ่มเติม ทั้งนี้ขึ้นอยู่กับคุณ
พฤติกรรมที่ต้องการ
กรณีการใช้งานของฉันคือแอปแชท การแชทสามารถมีข้อความได้นับพันข้อความ ฉันไม่ต้องการโหลดทั้งหมดทุกครั้ง สิ่งที่ฉันต้องการคือสร้างผู้ฟังที่เริ่มต้นที่ข้อความ n
ข้อความกลับ และสามารถขยายกลับด้วย n
ข้อความได้ตลอดเวลา น่าเสียดายที่ Firebase ไม่มีคุณสมบัติดังกล่าว แต่สิ่งที่เราทำได้คือสร้าง Listener ที่เริ่มต้นที่ข้อความ n
ข้อความกลับมา และแทนที่จะขยายออกไป เพียงสร้าง Listener อื่นสำหรับข้อความ n
ถัดไป
หวังว่าภาพวาดจะสมเหตุสมผล ผู้ฟังคนแรกของเราจะฟังข้อความล่าสุดและข้อความใหม่ที่เข้ามา ผู้ฟังคนที่สองจะฟังข้อความ n
ถัดไป คนที่สามสำหรับข้อความ n
หลังจากนั้น และอื่นๆ เราสามารถเพิ่มผู้ฟังต่อกันได้จนกว่าเราจะอ่านข้อความทั้งหมดจนหมด
เราจะใช้ตัวเลือกแบบสอบถามที่มีประโยชน์ซึ่ง firebase มีให้: orderBy()
, startAt()
, endBefore()
และ limit()
ช่วยให้เรากำหนดลำดับ ขีดจำกัด และขอบเขตในการสืบค้นของเรา
หากต้องการใช้ startAt()
และ endBefore()
เราต้องส่งสแนปชอตเอกสารให้พวกเขา สิ่งนี้จะทำให้เราวางขอบเขตบนและล่างให้กับผู้ฟังของเรา ในการรับสแนปชอตเอกสาร อันดับแรกเราต้องสร้างการสืบค้นแบบครั้งเดียวแบบง่ายๆ โดยมีขีดจำกัด n
เอกสาร เพื่อที่เราจะได้รับสแนปชอตเอกสารของข้อความที่เป็นข้อความ n
ข้อความกลับมา (เช่น ข้อความที่ 50 สุดท้าย)
รหัส
ตกลงนี่คือส่วนที่คุณทุกคนมาที่นี่เพื่อ:
var messages = [] var listeners = [] // list of listeners var start = null // start position of listener var end = null // end position of listener function getMessages(chatId) { // query reference for the messages we want let ref = db.collection('chats').doc(chatId) .collection('messages') // single query to get startAt snapshot ref.orderBy('createdAt', 'desc') .limit(50).get() .then((snapshots) => { // save startAt snapshot start = snapshots.docs[snapshots.docs.length - 1] // create listener using startAt snapshot (starting boundary) let listener = ref.orderBy('createdAt') .startAt(start) .onSnapshot((messages) => { // append new messages to message array messages.forEach((message) => { // filter out any duplicates (from modify/delete events) messages = messages.filter(x => x.id !== message.id) messages.push(message.data()) }) }) // add listener to list listeners.push(listener) }) } function getMoreMessages(chatId) { let ref = db.collection('chats').doc(chatId) .collection('messages') // single query to get new startAt snapshot ref.orderBy('createdAt', 'desc') .startAt(start) .limit(50).get() .then((snapshots) => { // previous starting boundary becomes new ending boundary end = start start = snapshots.docs[snapshots.docs.length - 1] // create another listener using new boundaries let listener = ref.orderBy('createdAt') .startAt(start).endBefore(end) .onSnapshot((messages) => { messages.forEach((message) => { messages = messages.filter(x => x.id !== message.id) messages.push(message.data()) }) }) listeners.push(listener) }) } // call to detach all listeners function detachListeners() { listeners.forEach(listener => listener()) }
ในการตั้งค่าผู้ฟังคนแรกที่เราเรียกว่า getMessages()
และเพื่อโหลดข้อความเก่าๆ ที่เราเรียกว่า getMoreMessages()
ฟังก์ชันทั้งสองเกือบจะเหมือนกัน ดังนั้นจึงสามารถรวมเป็นฟังก์ชันเดียวได้อย่างง่ายดาย แต่เพื่อความชัดเจนและความเรียบง่าย ฉันจึงแยกฟังก์ชันทั้งสองออกจากกัน
ข้อแตกต่างระหว่างสองฟังก์ชันที่ผู้ฟังคนแรกไม่ต้องการคือการใช้ endBefore()
เนื่องจากขอบเขตการสิ้นสุดจะป้องกันไม่ให้ฟังข้อความใหม่ ผู้ฟังคนอื่นๆ ทั้งหมดจำเป็นต้องมีขอบเขตเริ่มต้นและสิ้นสุด โดยผู้ฟังแต่ละคนมีขอบเขตร่วมกัน (เช่น ขอบเขตเริ่มต้นของผู้ฟัง 2 คือขอบเขตสิ้นสุดของผู้ฟัง 3 [อ้างอิงถึงรูปวาด])
เราจัดผู้ฟังไว้ในอาร์เรย์เพื่อให้เราสามารถแยกออกทั้งหมดได้อย่างง่ายดายเมื่อเราปิดหน้าต่างแชท
หวังว่านี่จะช่วยคุณในการแบ่งหน้าแบบโต้ตอบหรือโหลดกลับ ฉันจะติดตามผลด้วยบทช่วยสอนเพื่อใช้สิ่งนี้ด้วยการเลื่อนแบบไม่มีที่สิ้นสุด (เมื่อฉันเข้าใจแล้ว 😜)