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
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>
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
});
}
}
});
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.
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']
});
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:
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']
});
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 (12)
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. :)
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...
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
sdasd
Finally nice to see someone use Events over Vuex, even in the simple scenarios. Good post my dude.
Thank you! I like to use events when the project is simple ☺️
Gr8 Post !!! Will try to integrate the above with firestore !!
I would like to see the full code. Can you post it?
Sorry for my late reply. Here is the code: github.com/tsanak/comments created with vue cli 3.
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.
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)
Also make sure to finish all of Vue's documentation, I found it really helpful.
Nice