【问题标题】:How to use .hasChild and retrieve child using Firebase?如何使用 .hasChild 并使用 Firebase 检索孩子?
【发布时间】:2026-01-15 19:55:01
【问题描述】:

我正在开发一个具有以下 Firebase 结构的项目:

user {
  score: 0,
  messages : {
    key1 { name: name, text: text }
    key2 { name: name, text: text }
    key...
  }
}

我目前有两个问题。首先是确定用户是否有“消息”孩子,如果没有,则给它一个(连同分数),这是我到目前为止提出的代码:

  ref.once('value', function (snapshot) {
    if (!snapshot.hasChild("messages")) {
        ref.set({
            score: 0,
            messages: 0
        });
    }
});

接下来是在数据被推送给它后检索和显示来自孩子的消息,如下所示:

ref.child("messages").on('child_added', function (snapshot) {
    var message = snapshot.val();
    $('#messagesDiv').prepend(message.text ": " + message.name);
});

但这似乎也不起作用。

这是我制作的fiddle

我希望你们能帮我解决这个问题!语法看起来正确,我阅读了文档以找到大部分当前代码。

提前致谢!

【问题讨论】:

    标签: firebase


    【解决方案1】:

    设置初始数据

    您的带有hasChild 的代码似乎执行得很好。这没有多大意义。您添加的结构导致:

    user {
      score: 0,
      messages: 0
    }
    

    这与您在问题中绘制的结构不同:messages 这只是一个数字,而您希望它是消息的集合。此外,此更改将不会触发您的 child_added 处理程序,因为...您不会将孩子添加到 messages

    从设计数据结构开始,您已经做了正确的事情。下一步是确保您坚持使用该数据结构。因此,如果要添加初始消息,请以正确的结构添加消息:

    ref.once('value', function (snapshot) {
        if (!snapshot.hasChild("messages")) {
            ref.set({
                score: 0,
                messages: { 0: { name: 'puf', text: 'welcome' }}
            });
        }
    });
    

    如果您修改小提琴,您会看到welcome 消息确实显示在您的#messagesDiv 中。

    我认为这种方法仍然存在缺陷。除非您真的想添加欢迎消息,否则无需添加 messages 节点。我只需将 score 设置为 0,一旦用户输入他们的第一条消息,就会添加 messages 节点:

    ref.once('value', function (snapshot) {
        if (!snapshot.hasChild("messages")) {
            ref.set({ score: 0 });
        }
    });
    

    添加新消息

    我注意到您的小提琴中还有以下代码:

    $('#messageInput').keypress(function (e) {
        if (e.keyCode == 13) {
            var name = user;
            var text = $('#messageInput').val();
            // POST
            ref.child("messages").set({
                name: name,
                text: text
            });
            $('#messageInput').val('');
        }
    });
    

    输入处理很好,但您修改 Firebase 数据结构的代码再次与您开始提问时使用的数据结构不一致。如果我们执行这段代码,数据结构将是:

    user {
      score: 0,
      messages: {
          name: 'NotToBrag',
          text: 'asked 10 hours ago'
      }
    }
    

    如果不明显:此结构缺少 关键 key1 或您的结构。哦...它还覆盖了welcome 消息。

    当您将子节点添加到 Firebase 列表时,您几乎总是希望使用 push

            ref.child("messages").push({
                name: name,
                text: text
            });
    

    随着微小的变化,数据结构变成:

    user {
      score: 0,
      messages: {
          0: {
              name: 'puf',
              text: 'welcome'
          },
          '-Jh-aFN42nWef-FvgcfS': {
              name: 'NotToBrag',
              text: 'asked 10 hours ago'
          }
      }
    }
    

    所有这些(和往常一样)都是非常小的变化。但他们一起确保你的场景被严重破坏。我用来解决问题的技巧非常基本,您最好将它们添加到您的武器库中并学习使用它们。

    调试技巧一:console.log 数据结构

    每当我第一次收到某人问题的 MCVE 时,我都会立即记录他们的数据结构:

    new Firebase('https://your.firebaseio.com/').once('value', function(s) {
      console.log(s.val()); 
    })
    

    有时我可能会将 JSON 字符串化:

    new Firebase('https://your.firebaseio.com/').once('value', function(s) {
      console.log(JSON.stringify(s.val())); 
    })
    

    例如,最后一个 sn-p 是获取用于您的问题的数据结构的好方法。

    sn-p 只显示一次数据结构,所以每次发生变化时都要运行这个sn-p。

    调试技巧 2:删除数据

    您的整个hasChild sn-p 似乎旨在为用户设置您的初始数据结构。为了帮助测试,我经常删除数据:

    new Firebase('https://your.firebaseio.com/myName').remove()
    

    然后当你再次运行 fiddle 时,你可以看到你的 hasChild-using 代码做了什么。

    我经常在我的小提琴开始时使用代码来清理(或以其他方式重置)我的测试数据,或者只是从浏览器的 JavaScript 控制台运行一个 sn-p。

    【讨论】:

    • 感谢您的解释和技术! :) 我之前使用过 push 但它不起作用,所以我只是尝试设置数据。然而,我更新了我的小提琴,我仍然面临同样的Unexpected string 错误,我不知道它指的是什么或者为什么数据没有被发送到数据库(我之前顺便重置了它,所以它是@ 987654346@ 目前)。这是更新的小提琴:jsfiddle.net/rx4zgLzs/1(我不需要欢迎信息,但感谢您澄清这一点)。
    • 找到这样的语法错误的诀窍是注释掉代码块。如果消息仍然存在,则错误不在该代码中,请尝试另一个块。我将其本地化为这一行:$('#messagesDiv').prepend(message.text ": " + message.name);,但将留给您在那里找到实际问题。
    • 好的,我看到问题不敢相信我错过了,再次感谢,你帮了大忙!我将从现在开始评论并在发布之前使用调试技巧,对此感到抱歉。 :)
    • 现在如何让每个用户显示所有消息?就像全局聊天(即使用户名已更改)。我需要查询和按孩子订购吗?
    • 你的目标非常广泛。 * 并不是帮助您构建整个聊天应用程序的最佳媒介。如果您想查看 Firebase 上聊天应用程序的良好示例,请查看 Firechat。