firebase使用
In this tutorial, we are going to build an Event Booking App with HTML, CSS, JavaScript, and Firebase.
在本教程中,我们将使用HTML,CSS,JavaScript和Firebase构建一个Event Booking App。
规划我们的应用 (Plan our app)
We are not going to build a complete event booking app with all the functionality. We don't need to cover everything in just one tutorial. Since I just want to keep things simple and easy to digest, we'll go over the authentication part in a separate article.
我们不会构建具有所有功能的完整的事件预订应用程序。 我们不需要在一个教程中涵盖所有内容。 由于我只是想使事情简单易懂,因此我们将在另一篇文章中介绍身份验证部分。
So, our Event Booking App will have the following functionalities:
因此,我们的活动预订应用程序将具有以下功能:
- The user can create an event and store it to Firestore. 用户可以创建事件并将其存储到Firestore。
- The user can fetch all events in real-time. 用户可以实时获取所有事件。
- The user can book an event. 用户可以预订事件。
- The user can't book an event more than once. 用户最多只能预订一个活动。
Now that we know what our app will look like, let's start building it in the next section.
现在我们知道了我们的应用程序的外观,让我们在下一部分开始构建它。
标记 (Markup)
Our HTML file will be relatively simple. We will hold our navigation bar and the latest event in the header
tag.
我们HTML文件将相对简单。 我们将在header
标签中保留导航栏和最新事件。
In
index.html
在
index.html
<body>
<header id="home">
<nav class="navbar">
<h1>Eventic</h1>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#events">Events</a></li>
<li><a href="#add-event">New Event</a></li>
</ul>
</nav>
<div class="welcome-event"></div>
</header>
<main>
<section id="events">
<h1 class="section-title">Events</h1>
<div class="events-container"></div>
</section>
<section id="add-event">
<h1 class="section-title">New Event</h1>
<form class="form">
<input type="text" id="name" placeholder="Name">
<input type="number" id="attendee" placeholder="Attendees">
<textarea id="description" cols="30" rows="10" placeholder="Description..."></textarea>
<select id="status">
<option value="0">Free</option>
<option value="1">Paid</option>
</select>
<button class="btn btn-primary">Save</button>
</form>
</section>
</main>
Next, the main
tag will wrap the list of events and the form which enables us to create a new event.
接下来, main
标签将包装事件列表和表单,使我们能够创建新事件。
The events will be displayed later with the help of JavaScript.
稍后将在JavaScript的帮助下显示事件。
In
index.html
在
index.html
<script src="https://www.gstatic.com/firebasejs/7.9.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.9.1/firebase-firestore.js"></script>
<script>
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxxxxxxxxxxxxxxxx",
databaseURL: "xxxxxxxxxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxxxxxxxxxxxxxxxxxxx",
storageBucket: "xxxxxxxxxxxxxxxxxxxxxxxxx",
messagingSenderId: "xxxxxxxxxxxxxxxxxxxxxxxxx",
appId: "xxxxxxxxxxxxxxxxxxxxxxxxx"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore()
</script>
<script src="db.js"></script>
<script src="app.js"></script>
</body>
</html>
Next, we need to connect our app to Firebase to be able to store our data.
接下来,我们需要将我们的应用程序连接到Firebase才能存储我们的数据。
To have these credentials, you will need to create a new app in the Firebase Console. And once the project created, click on the code icon </>
that sits next to the iOS and Android icons to register your app.
要获得这些凭据,您将需要在Firebase控制台中创建一个新应用。 创建完项目后,单击iOS和Android图标旁边的代码图标</>
注册您的应用。
Now, to generate the credentials, you have to register the name of your app.And finally, put the credentials in the HTML file as I do here.
现在,要生成凭据,您必须注册您的应用程序名称。最后,像我在此处一样将凭据放入HTML文件中。
Next, duplicate the first script
tag and change firebase-app.js
to firebase-firestore.js
because we will use Firestore in this project.
接下来,复制第一个script
标签,并将firebase-app.js
更改为firebase-firestore.js
因为我们将在此项目中使用Firestore。
Then, initialize firebase
with the configuration and declare a db
variable that will be used later to interact with Firebase.
然后,使用配置初始化firebase
并声明一个db
变量,该变量将在以后与Firebase进行交互。
Now, we have our markup and have successfully linked our project to Firebase. So let's start styling it in the next section.
现在,我们有了标记,并已成功将我们的项目链接到Firebase。 因此,让我们在下一部分中开始设计样式。
造型 (Styling)
The CSS file is a bit long, so I won't cover everything in this post. I will just highlight the most important parts. However, no worries, you will find the source code at the end of the article.
CSS文件有点长,所以我不会在本文中介绍所有内容。 我将只重点介绍最重要的部分。 但是,不用担心,您将在本文结尾处找到源代码。
As usual, we start by importing our font and doing some resets to prevent the default behavior.
与往常一样,我们首先导入字体并进行一些重置以防止出现默认行为。
In
style.css
在
style.css
@import url('https://fonts.googleapis.com/css?family=Nunito:400,700&display=swap');
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
--primary-color:#e74c3c;
--secondary-color:#222;
--tertiary-color:#333;
--light-color: #fff;
scroll-behavior: smooth;
}
body {
background-color: #1f1f1f;
font-family: 'Nunito', sans-serif;
font-size: 1rem;
color: var(--light-color);
line-height: 1.6;
}
Next, we use CSS Variables to store our colors and set the scroll-behavior
to smooth
so we have a nice scrolling effect when the user clicks in the navbar links.
接下来,我们使用CSS变量存储颜色并将scroll-behavior
设置为smooth
以便在用户单击导航栏链接时具有很好的滚动效果。
However, be careful with the scroll-behavior
, as it's not supported by all browsers. You can check on browser compatibility here.
但是,请注意scroll-behavior
,因为并非所有浏览器都支持 scroll-behavior
。 您可以在此处检查浏览器的兼容性。
In
style.css
在
style.css
nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem 2.5rem;
z-index: 100;
width: 100%;
transition: background 0.3s;
position: fixed;
top: 0;
left: 0;
}
nav ul {
display: flex;
list-style: none;
}
nav li:not(:last-child), .welcome-event div span {
margin-right: 1.5rem;
}
For the navbar, by default, the background will be transparent. For better usability, it will change when the user starts scrolling.
对于导航栏,默认情况下,背景将是透明的。 为了更好的可用性,当用户开始滚动时它将改变。
Our Event Booking App is starting to take shape. Now let's start implementing Firebase and connect our app to Firestore.
我们的活动预订应用程序已初具规模。 现在,让我们开始实施Firebase并将我们的应用程序连接到Firestore。
与Firebase互动 (Interact With Firebase)
Firebase is a platform that handles everything related to the back-end for us. The only thing we have to do is connect our app to it and start using the database or other services.
Firebase是一个平台,可以为我们处理与后端相关的所有事情。 我们唯一要做的就是将我们的应用程序连接到它,然后开始使用数据库或其他服务。
Firestore is a NoSQL database, and it's non-relational and uses documents, collections, and so on to create the database.
Firestore是NoSQL数据库,它是非关系数据库,并使用文档,集合等来创建数据库。
Now, let's connect to Firestore and create our very first database.
现在,让我们连接到Firestore并创建我们的第一个数据库。
提取事件 (Fetch events)
Earlier in this tutorial, we had declared a variable db
in the HTML part. Now, let's use that variable to connect our app to Firestore.
在本教程的前面,我们在HTML部分中声明了一个变量db
。 现在,让我们使用该变量将我们的应用程序连接到Firestore。
I will put everything related to the database on the db.js
file to just have a cleaner structure.
我将与数据库相关的所有内容放在db.js
文件中,以使其结构更整洁。
In
db.js
在
db.js
db.collection('events').onSnapshot(snapshot => {
// Handle the latest event
const newestEvent = snapshot.docChanges()[0].doc.data()
const id = snapshot.docChanges()[0].doc.id
showLatestEvent(newestEvent, id);
// delete the latest event element
snapshot.docChanges().shift()
snapshot.docChanges().forEach(event => {
showEvents(event.doc.data(), event.doc.id)
});
})
With the help of db
, we can now access our collection events
. It's just the name of our database, and if it doesn't exist Firestore will create it on the fly for us.
在db
的帮助下,我们现在可以访问我们的收集events
。 它只是我们数据库的名称,如果不存在,Firestore会为我们动态创建它。
The collection object has a very handy method called onSnapshot()
. It helps us listen in real-time to the database. This means that whenever a change occurs on it, it will react and return the change in real-time.
集合对象有一个非常方便的方法,称为onSnapshot()
。 它可以帮助我们实时侦听数据库。 这意味着无论何时发生更改,它都会做出React并实时返回更改。
The onSnapshot()
method will also help us access the document (our data). And now, we can extract the latest event to show on the header. And, before looping through the events array, delete the latest event so that it doesn't display it again.
onSnapshot()
方法还将帮助我们访问文档(我们的数据)。 现在,我们可以提取最新事件以显示在标题上。 并且,在循环事件数组之前,请删除最新事件,以使其不再显示。
Now, to display the events on the UI, we have to call our necessary functions showLatestEvent()
and showEvents()
. Then we pass the event and the id to them as parameters.
现在,要在UI上显示事件,我们必须调用必要的函数showLatestEvent()
和showEvents()
。 然后,我们将事件和ID作为参数传递给他们。
We can now fetch the events from Firestore, but we still don't have any events to show. Let's store our very first event in our database.
现在,我们可以从Firestore中获取事件,但是仍然没有任何事件可以显示。 让我们将第一个事件存储在数据库中。
建立活动 (Create an event)
To get the values entered by the user, we have to first select the form
tag and use it to pick the id of each input and pull the value entered.
为了获得用户输入的值,我们必须首先选择form
标签,并使用它来选择每个输入的ID并提取输入的值。
In
db.js
在
db.js
const addNewEvent = () => {
const event = {
name: form.name.value,
attendee: form.attendee.value,
booked: 0,
description: form.description.value,
status: parseInt(form.status.value, 10)
}
db.collection('events').add(event)
.then(() => {
// Reset the form values
form.name.value = "",
form.attendee.value = "",
form.description.value = "",
form.status.value = ""
alert('Your event has been successfully saved')
})
.catch(err => console.log(err))
}
The db
variable (remember it's the reference to firebase.firestore()
) has another method to save data to Firestore: the save()
function. It's a promise, and once it's complete, we can now reset the values of the form and show a success message to the user.
db
变量(请记住是对firebase.firestore()
的引用)还有另一种将数据保存到Firestore的方法: save()
函数。 这是一个承诺,一旦完成,我们现在就可以重置表单的值并向用户显示成功消息。
Now, let's move on and handle the case when the user wants to book an event.
现在,让我们继续处理用户想要预订事件的情况。
预订活动 (Book an event)
As I said earlier, we can't check if the user is authenticated or not, so they can potentially book an event more than once.
如前所述,我们无法检查用户是否已通过身份验证,因此他们有可能多次预订活动。
So to handle this, I will use localStorage
to prevent booking duplication.
因此,为了解决这个问题,我将使用localStorage
防止预订重复。
In
db.js
在
db.js
let bookedEvents = [];
const bookEvent = (booked, id) => {
const getBookedEvents = localStorage.getItem('booked-events');
if (getBookedEvents) {
bookedEvents = JSON.parse(localStorage.getItem('booked-events'));
if(bookedEvents.includes(id)) {
alert('Seems like you have already booked this event')
}
else {
saveBooking(booked, id)
}
}
else {
saveBooking(booked, id)
}
};
const saveBooking = (booked, id) => {
bookedEvents.push(id);
localStorage.setItem('booked-events', JSON.stringify(bookedEvents));
const data = { booked: booked +1 }
db.collection('events').doc(id).update(data)
.then(() => alert('Event successfully booked'))
.catch(err => console.log(err))
}
And as you can see here, we first check if the event id is stored or not in localStorage. If it is, the user can't book the same event again. Otherwise, they will be able to book the event.
正如您在此处看到的那样,我们首先检查事件ID是否存储在localStorage中。 如果是,则用户无法再次预订同一事件。 否则,他们将可以预订活动。
And to update the booking counter, we use again db
to update the event on Firestore.
为了更新订票柜台,我们再次使用db
更新Firestore上的事件。
The db.js
file is now complete, So, let's move to the final part and connect our project to db.js
db.js
文件现在已完成,因此,让我们移至最后一部分并将我们的项目连接到db.js
使用JavaScript显示和更新数据 (Show and Update Data with JavaScript)
As usual, we start by selecting the necessary elements.
与往常一样,我们从选择必要的元素开始。
const eventsContainer = document.querySelector('.events-container')
const nav = document.querySelector('nav')
const welcomeEvent = document.querySelector('.welcome-event')
const form = document.querySelector('.form')
const showEvents = (event, id) => {
const {name, attendee, status, description, booked} = event
const eventStatus = status === 0 ? 'free': 'paid'
const output = `
<div class="card">
<div class="card--details">
<div>
<h1>${name}</h1>
<span>${attendee - booked} attendees</span>
</div>
<span class="card--details-ribbon ribbon-${eventStatus}">
${eventStatus}
</span>
<p>${description}</p>
<button onclick="bookEvent(${booked} ,'${id}')" class="btn btn-tertiary">Book</button>
</div>
</div>
`
eventsContainer.innerHTML += output;
}
Earlier in this article, we had passed as a parameter to the showEvents()
function the event fetched from Firestore in the db.js
file.
在本文的前面,我们已将db.js
文件中从Firestore提取的事件作为参数传递给showEvents()
函数。
We can now pull the values held on the event object and display it. And, when the user clicks on the button to book an event, we will call the bookEvent()
function to handle it.
现在,我们可以拉出事件对象上保存的值并显示它。 而且,当用户单击按钮预订事件时,我们将调用bookEvent()
函数来处理该事件。
const showLatestEvent = (latestEvent, id) => {
const {name, attendee, status, description, booked} = latestEvent
// Get the first event
welcomeEvent.innerHTML = `
<h1>${name}</h1>
<p>${description.length >= 100 ? `${description.substring(0, 100)}...` : description}</p>
<div>
<span>Attendees: ${attendee - booked}</span>
<span>Status: ${status === 0 ? 'free': 'paid'}</span>
</div>
<button onclick="bookEvent(${booked} ,'${id}')" class="btn btn-tertiary">Book</button>
`
}
form.addEventListener('submit', e => {
e.preventDefault()
addNewEvent()
})
window.onscroll = () => {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
nav.style.background = 'var(--tertiary-color)';
nav.style.boxShadow = '0 10px 42px rgba(25,17,34,.1)';
} else {
nav.style.background = 'none';
nav.style.boxShadow = 'none';
}
}
As you can see, the showLatestEvent()
method is quite similar to showEvents()
, unlike the element used to display the event.
如您所见,与用于显示事件的元素不同, showLatestEvent()
方法与showEvents()
非常相似。
And, when the description is a bit long, we use substring()
to truncate the value.
并且,当描述有点长时,我们使用substring()
截断该值。
Next, we listen to the form
element to handle the submit event and store it to Firestore with addNewEvent()
.
接下来,我们监听form
元素以处理addNewEvent()
事件,并使用addNewEvent()
将其存储到Firestore中。
And to make everything looking nice, when the user scrolls we add a background color and a box-shadow to the navigation bar.
为了使所有内容看起来都不错,当用户滚动时,我们在导航栏中添加了背景色和阴影。
With that change, we have now our Event booking App using JavaScript and Firebase.
有了这一更改,我们现在有了使用JavaScript和Firebase的活动预订应用程序。
Thanks for reading this article.
感谢您阅读本文。
You can check it live here or find the Source Code here.
Read more articles on my blog - Subscribe to my newsletter - Follow me on twitter
在我的博客上阅读更多文章 - 订阅我的新闻通讯 - 在Twitter上关注我
firebase使用