如何使用新的 Firebase (2016) 实现无限滚动?

Posted

技术标签:

【中文标题】如何使用新的 Firebase (2016) 实现无限滚动?【英文标题】:How to implement Infinite Scrolling with the new Firebase (2016)? 【发布时间】:2016-10-22 12:20:06 【问题描述】:

问题:

如何使用 javascript(和 node.js)在 Firebase 中实现高效的无限滚动?


我检查了什么:

Implementing Infinite Scrolling with Firebase?

问题:较旧的 firebase ^

Infinite scroll with AngularJs and Firebase


代码来自: Infinite scroll with AngularJs and Firebase

“首先,我建议在您的 Firebase 中创建一个索引。对于这个答案,我创建了这个:


   "rules": 
      ".read": true,
      ".write": false,
      "messages": 
         ".indexOn": "id"
      
   

那么,让我们用 Firebase 创造一些魔法吧:

// @fb: your Firebase.
// @data: messages, users, products... the dataset you want to do something with.
// @_start: min ID where you want to start fetching your data.
// @_end: max ID where you want to start fetching your data.
// @_n: Step size. In other words, how much data you want to fetch from Firebase.
var fb = new Firebase('https://<YOUR-FIREBASE-APP>.firebaseio.com/');
var data = [];
var _start = 0;
var _end = 9;
var _n = 10;
var getDataset = function() 
   fb.orderByChild('id').startAt(_start).endAt(_end).limitToLast(_n).on("child_added", function(dataSnapshot) 
      data.push(dataSnapshot.val());
   );
   _start = _start + _n;
   _end = _end + _n;

最后,一个更好的无限滚动(不带 jQuery):

window.addEventListener('scroll', function() 
  if (window.scrollY === document.body.scrollHeight - window.innerHeight) 
     getDataset();
   
);

我在 React 中使用了这种方法,无论您的数据有多大,它都非常快。”

(2015 年 10 月 26 日 15:02 回答)

(乔萨缪尔)


问题

在该解决方案中,每次滚动到达屏幕高度的末端时都会加载 n 个帖子。

根据屏幕大小,这意味着在某些时候会加载比需要更多的帖子(屏幕高度仅包含 2 个帖子,这意味着每次到达屏幕末尾时将加载超过必要的 3 个帖子例如,当 n = 5 时的高度)。

这意味着每次到达滚动高度的末尾时,3*NumberOfTimesScrollHeightHasBeenPassed 将加载比需要更多的帖子。


我的当前代码(一次加载所有帖子,不会无限滚动):

var express = require("express");
var router = express.Router();

var firebase = require("firebase");

router.get('/index', function(req, res, next) 

    var pageRef = firebase.database().ref("posts/page");

    pageRef.once('value', function(snapshot)
        var page = [];
        global.page_name = "page";
        snapshot.forEach(function(childSnapshot)
            var key = childSnapshot.key;
            var childData = childSnapshot.val();
            page.push(
                id: key,
                title: childData.title,
                image: childData.image
            );
        );
        res.render('page/index',page: page);
    );
);

【问题讨论】:

Firebase API 中没有进行任何更改以使无限滚动更容易或更难实现。它仍然是 API 的不理想用例。 【参考方案1】:

这里是无限分页的完整代码。

createPromiseCallback 函数用于支持 Promise 和回调。

function createPromiseCallback() 
  var cb;
  var promise = new Promise(function (resolve, reject) 
      cb = function (err, data) 
          if (err) return reject(err);
          return resolve(data);
      ;
  );
  cb.promise = promise;
  return cb;

函数getPaginatedFeed实现实际的分页

function getPaginatedFeed(endpoint, pageSize, earliestEntryId, cb) 
  cb = cb || createPromiseCallback();

 var ref = database.ref(endpoint);
  if (earliestEntryId) 
    ref = ref.orderByKey().endAt(earliestEntryId);
  
  ref.limitToLast(pageSize + 1).once('value').then(data => 
    var entries = data.val() || ;

    var nextPage = null;
    const entryIds = Object.keys(entries);
    if (entryIds.length > pageSize) 
        delete entries[entryIds[0]];
        const nextPageStartingId = entryIds.shift();
        nextPage = function (cb) 
            return getPaginatedFeed(endpoint, pageSize, nextPageStartingId,                     cb);
        ;
    
    var res =  entries: entries, nextPage: nextPage ;
    cb(null, res);
  );
  return cb.promise;

这里是如何使用getPaginatedFeed函数

var endpoint = '/posts';
var pageSize = 2;
var nextPage = null;
var dataChunk = null;
getPaginatedFeed(endpoint, pageSize).then(function (data) 
    dataChunk = data.entries;
    nextPage = data.nextPage;

    //if nexPage is null means there are no more pages left
    if (!nextPage) return;

    //Getting second page
    nextPage().then(function (secondpageData) 
        dataChunk = data.entries;
        nextPage = data.nextPage;
        //Getting third page
        if (!nextPage) return;

        nextPage().then(function (secondpageData) 
            dataChunk = data.entries;
            nextPage = data.nextPage;
            //You can call as long as your nextPage is not null, which means as long as you have data left
        );
    );

);

关于要在屏幕上放置多少项目的问题,您可以给出这样的解决方案,为每个帖子提供固定的 x 高度,如果需要更多空间,请在帖子底部放置“阅读更多”链接用户点击时会显示缺失的部分。在这种情况下,您可以在屏幕上保持固定数量的项目。此外,您可以检查屏幕分辨率以放置更多或更少的项目。

【讨论】:

应该何时以及如何触发提要?我想确保网站仅加载与屏幕高度一样多的帖子,并且仅在我们滚动 1*scrollHeight 时加载更多。 一开始你必须决定你想在屏幕上显示多少帖子,并用正确的pageSize初始化函数getPaginatedFeed(endpoint, pageSize),然后每次你的滚动事件触发你可以调用nextPage函数将为您提供另一块数据。仅当您到达数据底部时才会触发滚动事件。 但是我的滚动事件应该是什么?如果我做滚动高度,结果将保持不变:2 个帖子,无论大小如何,都将加载到屏幕上。如果 2 个帖子的总高度高于我的屏幕,那么我将加载不必要的数据,从而浪费带宽。如果 2 个帖子的总高度比我的屏幕尺寸小得多(如果我的屏幕很大),那么用户将不得不滚动更多的内容,并且每 2 个帖子之间会有很大的空白空间。这就是问题所在:/ 好的,我看到了你的问题,我的代码纯粹是无限滚动的后端实现,你要问的是更多的前端问题。所以我有几个选择。 1. 您可以以固定的 X 高度显示您的所有帖子,如果需要更多空间,您可以放置​​一个小按钮或链接,它会像所有社交网站一样显示“阅读更多”。 2. 屏幕大小不同的问题,你可以先检测屏幕的高度,然后根据这个决定你想放多少帖子(记住每个帖子应该有X高度) 我知道。但是我的问题的答案不能在 cmets 中:) 我不能接受不能满足我所表达问题的需要的答案。

以上是关于如何使用新的 Firebase (2016) 实现无限滚动?的主要内容,如果未能解决你的问题,请参考以下文章

如何在新的 Firebase 控制台中检查数据库和存储使用情况

如何使用命令行部署 Firebase 数据库安全规则?

如何在 Firebase 存储中创建文件夹?

如何在不退出的情况下使用 Firebase API 创建新用户? [复制]

如何使用 Authy+Amazon lambda+Firebase 实现 SMS/2FA 验证?

Google Play 游戏、Firebase 和新的 Google 登录