DEV Community

Cover image for Simple comment section with vue components
tsanak
tsanak

Posted on

Simple comment section with vue components

Recently I started to migrate the frontend part of my work from jquery to Vue.js and it feels amazing! I always liked working on the frontend, but working with Vue just feels right.

Since we try to migrate slowly we currently use the UMD build of vue and we just import it with a script tag. This allows us to make use of the majority of the features that the framework offers.

One of the last things I had to built was a small comment section, that will be used under some posts.

Sneak peek

alt text

When working with components I like to create a separate file for the app and a new file for each new component. This is a personal preference, others use different file structures.

Show me the code ๐Ÿค–

<div class="comments-outside">
    <div class="comments-header">
        <div class="comments-stats">
            <span><i class="fa fa-thumbs-up"></i> [[ likes ]]</span>
            <span><i class="fa fa-comment"></i> [[ comments.length ]]</span>
        </div>
        <div class="project-owner">
            <div class="avatar">
                <img :src="creator.avatar" alt="">
            </div>
            <div class="username">
                <a href="#">@[[ creator.user ]]</a>
            </div>
        </div>
    </div>
    <comments 
        :comments_wrapper_classes="['custom-scrollbar', 'comments-wrapper']"
        :comments="comments"
        :current_user="current_user"
        @submit-comment="submitComment"
    ></comments>
</div>
Enter fullscreen mode Exit fullscreen mode

The code of the app.

new Vue({
    el: '#app',
    delimiters: ['[[', ']]'],
    data: function() {
        return {
            likes: 12,
            //Info about the owner of the post
            creator: {
                avatar: 'http://via.placeholder.com/100x100/36846e',
                user: 'owner'
            },
            //Some info about the current user
            current_user: {
                avatar: 'http://via.placeholder.com/100x100/a74848',
                user: 'exampler'
            },
            //Comments that are under the post
            comments: [
                {
                    id: uuidv4(),
                    user: 'example',
                    avatar: 'http://via.placeholder.com/100x100/a74848',
                    text: 'lorem ipsum dolor lorem ipsum dolor lorem ipsum dolor',
                },
            ]
        }
    },
    methods: {
        submitComment: function(reply) {
            this.comments.push({
                id: uuidv4(),
                user: this.current_user.user,
                avatar: this.current_user.avatar,
                text: reply
            });
        }
    }
});
Enter fullscreen mode Exit fullscreen mode

This will be saved as a separate file named comments-app.js and will be included in the html.

So now we have the skeleton of the app and some data to get started, but we still have to make the comments component.

Preview:
alt text

Vue.component('comments', {
    delimiters: ['[[', ']]'],
    template: `
        <div class="comments">
            <div :class="comments_wrapper_classes">
                <single-comment 
                    v-for="comment in comments"
                    :comment="comment"
                    :key="comment.id"
                ></single-comment>
            </div>
            <hr>
            <div class="reply">
                <div class="avatar">
                    <img :src="current_user.avatar" alt="">
                </div>
                <input 
                    type="text" 
                    v-model.trim="reply" 
                    class="reply--text" 
                    placeholder="Leave a comment..."
                    maxlength="250"
                    required
                    @keyup.enter="submitComment"
                />
                <button 
                    class="reply--button" 
                    @click.prevent="submitComment">
                    <i class="fa fa-paper-plane"></i> Send
                </button>
            </div>
        </div>
    `,
    data: function() {
        return {
            reply: ''
        }
    },
    methods: {
        //Tell the parent component(main app) that we have a new comment
        submitComment: function() {
            if(this.reply != '') {
                this.$emit('submit-comment', this.reply);
                this.reply = '';
            }
        }
    },
    //What the component expects as parameters
    props: ['comments', 'current_user', 'comments_wrapper_classes']
});
Enter fullscreen mode Exit fullscreen mode

This will be put into a new file named comments.js and we will include it with a script tag in the app.
As you can see we have a new component named single-comment that we need to build (I promise this is the last one ๐Ÿ˜…).
Preview:
alt text

Vue.component('single-comment', {
    delimiters: ['[[', ']]'],
    template: `
        <div class="comment">
            <div class="avatar">
                <img :src="comment.avatar" alt="">
            </div>
            <div class="text">
                <a class="username" href="#">
                    @[[ comment.user ]]
                </a> 
                <span>[[ comment.text ]]</span>
            </div>
        </div>
    `,
    props: ['comment']
});
Enter fullscreen mode Exit fullscreen mode

This will be put into a new file named single-comment.js and we will include it with a script tag in the app.

Conclusion

Personally whenever I have to create anything I break it down into components and ask myself some questions:
1.Could this be used anywhere else?
2.Does it make sense to be used, as is, somewhere else?
If the answer is yes I create the component.

๐ŸŽ‰Thank you for reading through all this and I hope you found something helpful๐ŸŽ‰

Let me know if you would like to see the full code, with the css and I will create a github repo.

Top comments (13)

Collapse
 
hoodlumz profile image
David Elstob

Nice post. Thanks. Just looking for a comment section for my Gridsome site and they recommend Disqus, but that will probably be too slow for my liking.

Your solution should be much faster, I presume?

Well I can only try and see how it goes. :)

Collapse
 
celyes profile image
Ilyes Chouia • Edited

when using disqus, don't show it right after the loading... let the user click "show comments" button which when clicked, loads the disqus system... i use this approach as a work-around to this problem as well as to achieve a good score in Google Lighthouse...

Collapse
 
tsanak profile image
tsanak

Sorry for my late reply.

Thank you for your comment!

I think Disqus offers a good solution for adding comments to your website, I have not tested the perfomance of it though.

The problem with my solution is that it doesn't have any backend so you should think of a way to handle listing & adding comments.

If you used this "plugin", then please let me know if you encountered any issues.

Full code can be found in github.com/tsanak/comments

Collapse
 
biefeng profile image
biefeng • Edited

sdasd

Collapse
 
itsmrsammeh profile image
Sam Parton

Finally nice to see someone use Events over Vuex, even in the simple scenarios. Good post my dude.

Collapse
 
tsanak profile image
tsanak

Thank you! I like to use events when the project is simple โ˜บ๏ธ

Collapse
 
shriaviator profile image
shriaviator

Gr8 Post !!! Will try to integrate the above with firestore !!

Collapse
 
dgleba profile image
dgleba

I would like to see the full code. Can you post it?

Collapse
 
tsanak profile image
tsanak

Sorry for my late reply. Here is the code: github.com/tsanak/comments created with vue cli 3.

Collapse
 
carlosjdelgadonovaims profile image
carlosjdelgadonovaims

Hello, thank you so much for this example, I'd like to see all the code, is that possible?. Or see like a demo, I'm new working with VueJs, so I'll appreciate if you can provide the complete code.

Collapse
 
tsanak profile image
tsanak

Thank you for your comment.
Here is the code: github.com/tsanak/comments created with vue cli 3.

If you want you can check my other articles on Vue (repos included)

  1. Make your life easier with vuejs
  2. Building an image carousel with vuejs

Also make sure to finish all of Vue's documentation, I found it really helpful.

Collapse
 
orazcharyar profile image
OrazCharyar

Nice