简体   繁体   English

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

[英]How to create a dynamic HTML table with Firebase?

I'm trying to create an HTML table that can be updated in real time with firebase as my users use my app. 我正在尝试创建一个HTML表,当用户使用我的应用程序时,可以使用firebase实时更新该表。 I'm really struggling on getting this to work, I don't really know where to start. 我真的很想让它开始工作,我真的不知道从哪里开始。

basically, all it needs to do is create a new table row and update its cells in real time as the user is interacting with my app. 基本上,它所要做的就是创建一个新的表行,并在用户与我的应用进行交互时实时更新其单元格。

Does anyone know of any good tutorials that could point me in the right direction? 有人知道有什么好的教程可以为我指明正确的方向吗? Examples of code on creating the HTML table would also be great! 创建HTML表的代码示例也很棒! thanks. 谢谢。

UPDATE: OK! 更新:好的! thanks to Isaiah Lee, I went out and looked up some tutorials for React. 感谢Isaiah Lee,我出去看看了React的一些教程。 I'm 90% there but there is one problem I can't seem to figure out... 我在那里90%,但似乎有一个我似乎无法解决的问题...

I'm able to update my table with new rows dynamically as the users use my app, but I can't get them to fill up with data. 当用户使用我的应用程序时,我可以动态地用新行更新表,但是我无法让它们填充数据。 I feel like I'm really close but my inexperience with React is holding me back here... 我觉得我真的很接近,但是我对React的经验不足使我退缩到这里...

for some reason, this loop here doesn't populate the td's with any data 由于某种原因,此循环不会在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>
);

} }

Heres my components function 这是我的组件功能

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()
          })
      });

     }


    }

Sounds like you should look into some frontend framework. 听起来您应该研究一些前端框架。 In your particular use case, anything with 1-way binding will work (eg react). 在您的特定用例中,任何具有1向绑定的东西都可以工作(例如,反应)。 And of course, anything with 2-way binding will work as well (angular). 当然,任何带有2向绑定的东西也都可以工作(角度)。

Egghead.io has really well done, bite-size tutorials that can get you running shortly: https://egghead.io/browse/frameworks Egghead.io确实做得很好,一口大小的教程可以使您很快运行: https ://egghead.io/browse/frameworks

Edit: 编辑:

Okay, it's been over a year since I've last been working with react, but I have some ideas that could help. 好的,自从我上次进行反应以来已经一年多了,但是我有一些想法可以帮到您。

First, react is all about separating components and breaking things off into smaller bits. 首先,反应就是将组件分离并将其分解成较小的部分。 The idea is that you have some state change at the top level, those changes are propagated down into the nested components using props. 这个想法是您在顶层进行了一些状态更改,这些更改使用props向下传播到嵌套组件中。

I'd recommend you have a top level component that listens for changes in Firebase (I havent worked with FB in a long time either), and then sends those down to components that render based on the data. 我建议您有一个顶层组件,侦听Firebase中的更改(或者我很长时间没有使用FB),然后将这些更改发送到根据数据进行渲染的组件。 I recommend reading this article written by Dan Abramov (creator of Redux), which discusses smart vs dumb components: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0 我建议阅读由Dan Abramov(Redux的创建者)撰写的这篇文章,其中讨论了智能组件和哑组件: https : //medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0

Again, I haven't used react in a while, so I'll use pseudocode to describe how you might want to design this. 同样,我已经有一段时间没有使用react了,所以我将使用伪代码来描述您可能如何设计它。

Top Level Component This component should be the only place your app is interacting with Firebase. 顶级组件此组件应该是您的应用与Firebase进行交互的唯一位置。 You'll configure all the listeners here such that when new data is received, it simply propagates down to child components. 您将在此处配置所有侦听器,以便在接收到新数据时,它仅向下传播到子组件。

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>
    );
}

Row Component You have a separate component that receives a log object through props and renders a single row. 行组件您有一个单独的组件,该组件通过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>
    );
}

The above TableRow is an example of a dumb component. 上面的TableRow是一个哑组件的示例。 It doesn't hold any internal state, nor really modify anything. 它没有任何内部状态,也没有任何修改。 It just takes what it's given via props and renders what it's supposed to. 它只是接受通过道具给出的内容,并渲染其应有的内容。

Again, you'll have to consider my examples above as pseudocode, it wouldn't work if you tried to copy and run it. 同样,您必须将我上面的示例视为伪代码,如果您尝试复制并运行它,它将无法正常工作。 But hopefully this gives you some insight into how to design components in react. 但是希望这可以使您对如何设计组件做出一些了解。 Remember, "everything is a component". 记住,“一切都是组成部分”。

Just a couple last notes: 最后几条注意事项:

  1. Components are more useful the more generic they are. 组件越通用,则越有用。 The ideal scenario is that you create a component, and if you need something similar later, you can just take the component you already created and plug it in with slight modifications (or in the best case scenario, no change at all!). 理想的情况是创建一个组件,如果以后需要类似的东西,则只需取出已经创建的组件,然后稍加修改即可插入(最好的情况下,完全不要更改!)。 So if you see yourself needing a bunch of similar tables in your app, you'll want to further generalize my example. 因此,如果您发现自己的应用程序中需要一堆类似的表,则需要进一步概括我的示例。 For example, the firebase ref explicitly connects with the "logs" collection, making this table component only useful for that one object type. 例如,firebase ref显式连接“ logs”集合,从而使该表组件仅对一种对象类型有用。 You'll want to make the parent component receive either a table name, or an already initialized firebase reference, that it can use. 您将要使父组件接收可以使用的表名或已初始化的Firebase引用。 That way, the component is not tied down to a specific firebase table. 这样,该组件就不会绑定到特定的Firebase表。 The mapping function should also be passed in, as the one in my example is hardcoded to map a "log" object, and you may be wanting to grab other types from firebase. 映射函数也应该传入,因为在我的示例中,该函数被硬编码为映射“ log”对象,并且您可能想从firebase中获取其他类型。
  2. I learned a lot from reading and messing around, but honestly this one Udemy class I took really nailed down all the concepts for me: https://www.udemy.com/react-redux/ I'd highly recommend taking it, although you'd probably want to wait until Udemy has a site-wide sale where you can get the course for $10-20 bucks. 我从阅读和弄乱中学到了很多东西,但老实说,我参加的这门Udemy课程确实为我确定了所有概念: https ://www.udemy.com/react-redux/我强烈建议您参加,尽管您可能要等到Udemy在整个网站进行销售,您才能以$ 10-20的价格获得这门课程。 I've taken several of his courses and they've all been well worth the money. 我选了几门他的课程,他们都非常值得。

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM