Image

build-a-gmail-clone-with-vue-3

5 min read
Last update: December 19, 2021

Building the Inbox

For the starting code for this lesson, switch to branch: https://github.com/Code-Pop/build-gmail-clone-with-vue-3/tree/video-2-start

What we’ll be doing

This lesson builds up the basic display of the inbox screen, re-introducing concepts from Vue 2 and showing that the Options API still works in a Vue 3 app.

We’ll display emails as a table, mark emails as read when they’re clicked, display dates properly, sort and filter the emails, and add an archive button.

If you want to code along, you can download the starter code from https://github.com/Code-Pop/build-gmail-clone-with-vue-3 and use the video-2-start branch. The finished code is in the video-2-end branch. This code includes some CSS, data, and packages that aren’t included with the standard VueCLI output.


Updating VSCode’s Vetur for Vue 3

In Vue 3 we can have multiple root tags. However, currently this shows up as an ESLint error.

To fix this, go to Code > Preferences > Settings, search for ESLint, and uncheck “Validate vue-html in <template> using eslint-plugin-vue”.


Creating the Email Table

We’ll loop through the emails and put them in a table.

We’ll show a checkbox, a ‘from’ field, a field that contains the subject and the first part of the email body, and then a date.

We’ll be using hard-coded data for the emails for now.

<div id="app">
    <h1>VMail Inbox</h1>

    <table class="mail-table">
        <tbody>
            <tr v-for="email in emails" :key="email.id" class="clickable">
                <td>
                    <input type="checkbox" />
                </td>
                <td>{{email.from}}</td>
                <td>
                    <p><strong>{{email.subject}}</strong> - {{email.body}}</p>
                </td>
                <td class="date">{{email.sentAt)}}</td>
            </tr>
        </tbody>
    </table>
</div>
export default {
name: 'App',
data(){
return {
emails: [
{
"id": 1,
"from": "team@vuemastery.com",
"subject": "What's up with Vue 3.0? Here's how to find out from Evan You",
"body": "The opening keynote of VueConf US this year was Evan You (the creator of Vue), giving his State of the Vuenion address. He walked us through the journey of getting Vue 3 from a prototype to a reality the past year. He also dove into Vue's overall growth in the community.",
"sentAt": "2020-03-27T18:25:43.511Z",
"archived": false,
"read": true
},
{
"id": 2,
"from": "jeffrey@vuescreencasts.com",
"subject": "Five new VueJS videos this week + new podcast episode",
"body": "I hope you've been enjoying the Vue 3 course I've been releasing with Vue Mastery!\n\nThis week on VueScreencasts.com we have a follow-up video that digs further into what we covered in this week's Vue Mastery lesson, I answer a question that five of you asked about last week's most popular video, and we start a new series with a very awesome library author.\n\nFinally, for your ears only: a new episode of Exploring the Vueniverse.",
"sentAt": "2020-05-03T18:25:43.511Z",
"archived": false,
"read": false
},
{
"id": 3,
"from": "damian@dulisz.com",
"subject": "#177: Updated Vue.js Roadmap; Vuex v4.0.0-alpha.1 has been released; Kia King Ishii join the core team; Nuxt v2.12 released; Videos from Vue.js Amsterdam 2020 are here!",
"body": "First of all, lets congratulate Kia King Ishii on joining the Vue.js core team! 🎉 He has been doing an incredible job building vuex-orm and will now focus on working on the next versions of Vuex.\n\nSpeaking of which – Vuex v4.0.0-alpha.1 has just been released! This is the version of Vuex that will work with Vue 3.0 but keep the familiar API you know from the current version.",
"sentAt": "2020-03-18T18:25:43.511Z",
"archived": false,
"read": false
},
{
"id": 4,
"from": "anthony@vuejsdevelopers.com",
"subject": "'Vue 3 Release Roadmap' + 6 more must-read articles from this week",
"body": "Newsletter Issue #161",
"sentAt": "2020-03-24T18:25:43.511Z",
"archived": true,
"read": false
}
]
}
},

https://firebasestorage.googleapis.com/v0/b/vue-mastery.appspot.com/o/flamelink%2Fmedia%2FBuildGmail2-1.opt.jpg?alt=media&token=98cc2a76-fb70-4e0e-8a16-186f6b7157e1


Adding dynamic classes and click events

Let’s add some old standby Vue 2 techniques.

We’ll add dynamic elements to the classes, using a dynamic class array and a click event. Read emails will display with a grey background.

<tr v-for="email in emails" :key="email.id" :class="[email.read ? 'read': '', 'clickable']" @click="email.read = true">

Formatting dates

Then we’ll use the date-fns library to make the date display better. Date-fns is like a lightweight moment.js.

import { format } from 'date-fns';

export default {
name: 'App',
data(){
let emails = [...]
return {
format,
emails
}
}
}
<td class="date">{{format(new Date(email.sentAt), 'MMM do yyyy')}}</td>

Sorting and filtering

Then we’ll sort and filter our data using computed properties.

We’ll want it so that the most recently received emails are shown first. We’ll also want archived emails to not display.

computed: {
unarchivedEmails(){
return this.sortedEmails.filter(e => !e.archived)
},
sortedEmails(){
return this.emails.sort((e1, e2) => {
return e1.sentAt < e2.sentAt ? 1 : -1 }) } } ``` ```html <tr v-for="email in unarchivedEmail" :key="email.id" :class="[email.read ? 'read': '', 'clickable']" @click="email.read = true">

Archive Button

Finally, we’ll add an archive button, so we can remove emails from our inbox.

<td><button @click="email.archived = true">Archive</button></td>

Conclusion

So we’ve built a nice basic Vue 3 app using just the techniques we know from Vue 2… but in the upcoming lessons we’re going to take advantage of new Vue 3 features to make our app even better.

https://firebasestorage.googleapis.com/v0/b/vue-mastery.appspot.com/o/flamelink%2Fmedia%2FBuildGmail2-2.jpg?alt=media&token=b08d84ed-91d7-4332-a88b-14018bfb3446

For the ending code for this lesson, switch to branch: https://github.com/Code-Pop/build-gmail-clone-with-vue-3/tree/video-2-end

Jeffrey teaches an 8-week beginning Vue course with guaranteed results. Built on top of the VueMastery curriculum, with extra hands-on assignments and personal attention. You can find it here.