javascript - 如何使用 Firebase 创建动态 HTML 表格?

标签 javascript html reactjs firebase firebase-realtime-database

我正在尝试创建一个 HTML 表格,当我的用户使用我的应用程序时,该表格可以使用 firebase 实时更新。我真的很难让它发挥作用,我真的不知道从哪里开始。

基本上,它所需要做的就是创建一个新的表格行并在用户与我的应用程序交互时实时更新其单元格。

有谁知道有什么好的教程可以为我指明正确的方向吗?创建 HTML 表格的代码示例也很棒!谢谢。

更新: 好的!感谢 Isaiah Lee,我出去查找了一些 React 教程。我已经完成了 90%,但有一个问题我似乎无法解决......

当用户使用我的应用程序时,我可以用新行动态更新我的表,但我无法让它们填充数据。我觉得我已经很接近了,但我对 React 的缺乏经验阻碍了我……

出于某种原因,这里的循环不会使用任何数据填充 td

render() {
return (
  <div className="App">

    <h1>Talkeetna Numbers</h1>
    <table id="numbers">
      <tbody>
        <tr>
          <th>Driver</th>
          <th>Coach</th>
          <th>Time</th>
          <th>Total People</th>
          <th>AM Train</th>
          <th>PM Train</th>
          <th>MEX</th>
          <th>Employees</th>
          <th>Seats Left</th>

        </tr>

        {this.state.rows.map(row =>
        <tr>
          <td>{this.state.driver}</td>
          <td>{this.state.coach}</td>
          <td>{this.state.time}</td>
          <td>{this.state.totalPeople}</td>
          <td>{this.state.amTrain}</td>
          <td>{this.state.pmTrain}</td>
          <td>{this.state.THEMEX}</td>
          <td>{this.state.Employees}</td>
          <td>{this.state.seatsLeft}</td>
        </tr>)}

    </tbody>
  </table>



  </div>
);

}

这是我的组件功能

componentDidMount()
{
  const logsRef = firebase.database().ref('logs');

  logsRef.on('child_added', snap => {


  this.addRow(snap.getKey());
  //rows.push(snap.getKey());
  console.log("adding key: ", snap.getKey());


   });

   console.log("loading rows...");

   for(var rowKey = 0; rowKey < this.state.rows.length; rowKey++)
   {

      const root = firebase.database().ref().child('logs/' + rowKey);
      const driverRef = root.child('Driver');
      const coachRef = root.child('Coach');
      const timeRef = root.child('Time');
      const totalPeopleRef = root.child('Total People');
      const AMTrainRef = root.child('AM Train');
      const PMTrainRef = root.child('PM Train');
      const MEXRef = root.child('MEX');
      const EmployeesRef = root.child('Employees');
      const seatsLeftRef = root.child('Seats Left');

      //sync with DB in real time
      driverRef.on('value', snap => {
        this.setState({
          driver: snap.val()
          })
        });
       coachRef.on('value', snap => {
         this.setState({
         coach: snap.val()
       })
       });
       timeRef.on('value', snap => {
       this.setState({
       time: snap.val()
          })
       });

       totalPeopleRef.on('value', snap => {
       this.setState({
        totalPeople: snap.val()
         })
       });

       AMTrainRef.on('value', snap => {
       this.setState({
       amTrain: snap.val()
          })
       });

      PMTrainRef.on('value', snap => {
      this.setState({
      pmTrain: snap.val()
        })
      });
      MEXRef.on('value', snap => {
        this.setState({
       THEMEX: snap.val()
        })
       });
      EmployeesRef.on('value', snap => {
      this.setState({
      Employees: snap.val()
       })
       });
       seatsLeftRef.on('value', snap => {
          this.setState({
          seatsLeft: snap.val()
          })
      });

     }


    }

最佳答案

听起来你应该研究一些前端框架。在您的特定用例中,任何具有单向绑定(bind)的东西都可以工作(例如 react )。当然,任何具有 2 向绑定(bind)的东西都可以工作( Angular )。

Egghead.io 有非常好的、简短的教程,可以让你很快上手:https://egghead.io/browse/frameworks

编辑:

好吧,距离我上次使用 React 已有一年多了,但我有一些想法可以提供帮助。

首先,React 就是分离组件并将事物分解成更小的部分。这个想法是,您在顶层有一些状态更改,这些更改使用 props 向下传播到嵌套组件中。

我建议您使用一个顶级组件来监听 Firebase 中的更改(我也很长时间没有使用 FB),然后将这些组件发送到基于数据进行渲染的组件。我建议阅读 Dan Abramov(Redux 的创建者)撰写的这篇文章,其中讨论了智能组件与dumb组件:https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0

再说一遍,我有一段时间没有使用 React,所以我将使用伪代码来描述您可能想要如何设计它。

顶级组件 此组件应该是您的应用与 Firebase 交互的唯一位置。您将在此处配置所有监听器,以便在收到新数据时,它只是向下传播到子组件。

constructor() {

    this.firebaseRef = firebase
        .database()
        .ref('logs');

    this.state = {
        logs: []
    };

    // when the table first loads, use the
    // firebase ref to get all the current data
    // and initialize/render the table. After this,
    // you should only be listening for when a new row
    // (or "log") is added. Pseudocode:
    firebase.database().ref('logs')
        .all()
        .then(logs => {
            // project all the logs into the model we need and set to 
            // component's row state
            this.state.logs = logs.map(logMapper);
        });
}

// takes in a log that you get from firebase and maps
// it to an object, modeled such that it contains all 
// the information necessary for a single table row
logMapper(log) {
    return {
        driver: log.child('Driver'),
        time: log.child('Time'),
        ...
    };
}

componentDidMount() {
    const logsRef = firebase
        .database()
        .ref('logs');

    firebaseRef.on('child_added', log => {
        this.state.logs.push(logMapper(log));
    });
}


render() {
    return (
        <table id="numbers">
            <thead>
                <th>Driver</th>
                <th>Coach</th>
                <th>Time</th>
                <th>Total People</th>
                <th>AM Train</th>
                <th>PM Train</th>
                <th>MEX</th>
                <th>Employees</th>
                <th>Seats Left</th>             
            </thead>
            <tbody>
                {this.state.logs.map(row => <TableRow rowData="logs" />}
            </tbody>
        </table>
    );
}

行组件 您有一个单独的组件,它通过 props 接收日志对象并呈现单行。

render() {
    return (
        <tr>
            <td>{this.props.rowData.driver}</td>
            <td>{this.props.rowData.coach}</td>
            <td>{this.props.rowData.time}</td>
            <td>{this.props.rowData.totalPeople}</td>
            <td>{this.props.rowData.amTrain}</td>
            <td>{this.props.rowData.pmTrain}</td>
            <td>{this.props.rowData.THEMEX}</td>
            <td>{this.props.rowData.Employees}</td>
            <td>{this.props.rowData.seatsLeft}</td> 
        </tr>
    );
}

上面的 TableRow 是一个dumb组件的示例。它不保存任何内部状态,也不真正修改任何内容。它只是获取通过 props 提供的内容并呈现它应该呈现的内容。

同样,您必须将上面的示例视为伪代码,如果您尝试复制并运行它,它将无法工作。但希望这能让您深入了解如何在 React 中设计组件。请记住,“一切都是组件”。

最后几点说明:

  1. 组件越通用,就越有用。理想 场景是你创建一个组件,如果你需要一些东西 稍后类似,您可以只使用已经创建的组件 并稍作修改即可将其插入(或者在最好的情况下 场景,根本没有改变!)。所以如果你发现自己需要一堆 如果您的应用程序中存在类似的表格,您将需要进一步概括我的 例子。例如,firebase ref 显式连接 “logs”集合,使得该表组件仅对该一种对象类型有用。 您需要让父组件接收一个表 名称,或它可以使用的已初始化的 firebase 引用。 这样,该组件就不会绑定(bind)到特定的 firebase table 。还应该传入映射函数,如 我的示例被硬编码为映射“日志”对象,您可能会 想要从 firebase 获取其他类型。
  2. 我从阅读和闲逛中学到了很多东西,但老实说,我参加的这堂 Udemy 类(class)确实为我明确了所有概念:https://www.udemy.com/react-redux/ 我强烈建议您参加该类(class),尽管您可能需要等到 Udemy 进行全站促销,您可以花 10-20 美元购买该类(class)。我选修了他的几门类(class),而且这些类(class)都非常物有所值。

祝你好运!

关于javascript - 如何使用 Firebase 创建动态 HTML 表格?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43795566/

相关文章:

javascript - 对象函数作用域

javascript - 当我尝试动态设置高度时 map 不加载

javascript - 无法访问回调函数 React 中的属性

html - 未应用图像的 CSS 行高

reactjs - Apollo Client React 容器将创建的元素添加到分页元素列表中而无需重新获取

javascript - 当没有 child 时删除图标

javascript - 一次只允许执行一个 jQuery 函数

javascript - 如何包含适用于 Node.js 的 Amazon EC2 库?

javascript - Douglas Crockford 所说的 'constructed in a different window or frame' 是什么意思?

html - 单击导航按钮时如何关闭导航栏?