Hệ thống bình luận của blogger thường nổi tiếng là nguyên nhân chính khiến trang của bạn bị chậm. Nguyên nhân chính do sự delay khá lâu từ phía server blogger khi load iframe thêm vào đó là một đống js (nếu bài có ít nhất 1 bình luận thì lượng js phải tải lên tới gần 500KB). Tuy nhiên sau khi đọc xong bài viết này bạn sẽ yêu thích nó hơn bao giờ hết
Với sự phối hợp linh hoạt từ mã XML, bạn hoàn toàn có thể load được iframe và lấy được nội dung bình luận từ cơ sở dữ liệu mà không cần dùng tới js.
Trong bài này tôi sẽ hướng dẫn bạn cách xây dựng hệ thống bình luận phân làm 2 cấp (hiện khá phổ biến trên các trang mạng xã hội)
Hệ thống bình luận blogger chia làm 2 phần
- Phần viết bình luận (chính là cái iframe lâu la kia): sẽ được load cả trong trang bài viết có bình luận (threaded comment) cũng như bài viết không có bình luận
- Phần hiển thị nội dung bình luận: chỉ hiển thị ở những bài viết có bình luận
Để phân cấp bình luận blogger cung cấp cho ta hàm inReplyTo giúp xác định gia phả bình luận, mỗi bình luận "cha" sẽ có một id để các bình luận "con" có thể chui vào
Theo như phân tích cấu trúc như trên code của tôi sẽ như sau
Phần viết bình luận sẽ bao gồm code của iframe, phần hiển thị bình luận sẽ được viết tiếp như sau
Cứ lặp như vậy bạn có thể xây dựng hệ thống bình luận hiển thị theo nhiều cấp độ. FontAwesome sử dụng trong bài viết v5
Viết css cơ bản
.level1{margin: 0 0 1em}
.level2{margin: 0 0 0 40px}
.comments-form>h4{padding: 0 0 0 4px;letter-spacing: .02rem;font-size: 16px;margin:1em 0 0}
.comment-thread{font-family:arial,sans-serif;font-size:15px}
.comment-header{clear:both}
.comment-avatar img{border-radius:100%;width:35px;float:left;height:35px;margin:0 13px 0 0}
.comment-date{font-size:14px;margin:0 0 6px}
.comment-author a{font-weight:bold;color:#000}
.comment-content{padding:0 0 0 47px;margin:0 0 15px;line-height:1.4}
.comment-author,.comment-date{position:relative;display:block}
.comment-reply{color:#313131;text-decoration:none;font-size:12px;font-family:arial,sans-serif;font-weight:bold;display:inline-block;margin:0 0 10px;cursor:pointer}
Dữ liệu hiển thị tôi lấy sẽ bao gồm ảnh đại diện, người bình luận, thời gian bình luận và nội dung bình luận. Nếu bạn muốn thêm gì nữa thì tùy miễn là đúng thẻ gọi dữ liệu. Tham khảo bài viết Thẻ gọi dữ liệu tiện ích bài đăng Blog1
Với widget Blog1 v2
Đăng kí mới 1 thẻ b:includable
<b:includable id='hung1001Comments' var='post'>
<div id='comments-holder'>
<div class='comments-form'>
<h4><i class='fas fa-pen-nib' /> <data:messages.postAComment/></h4>
<iframe allowtransparency='true' class='blogger-iframe-colorize blogger-comment-from-post' expr:src='"https://www.blogger.com/comment-iframe.g?blogID=" + data:blog.blogId + "&" + (data:view.isPost ? "postID" : "pageID") + "=" + data:post.id + "&skin=soho"' frameborder='0' id='comment-editor' name='comment-editor' width='100%' />
</div>
<b:if cond='data:post.numberOfComments gt 0'>
<div class='comment-thread'>
<b:loop values='data:post.comments' var='commentLevel1'>
<b:if cond='!data:commentLevel1.inReplyTo'>
<div class='level1'>
<div class='comment-header'>
<span class='comment-avatar'><img expr:src='resizeImage(data:commentLevel1.authorPhoto.url, 35, "1:1")'/></span>
<span class='comment-author'><a expr:href='data:commentLevel1.authorUrl'><data:commentLevel1.author/></a></span>
<span class='comment-date' expr:title='data:commentLevel1.timestamp'><data:commentLevel1.timestamp/></span>
</div>
<div class='comment-content'>
<data:commentLevel1.body/>
</div>
<div class='comment-action'>
<a class='comment-reply' expr:data-href='"https://www.blogger.com/comment-iframe.g?blogID=" + data:blog.blogId + "&" + (data:view.isPost ? "postID" : "pageID") + "=" + data:post.id + "&parentID=" + data:commentLevel1.id + "&skin=soho"' href='javascript:void(0)'>REPLY</a>
</div>
<b:loop values='data:post.comments' var='commentLevel2'>
<b:if cond='data:commentLevel2.inReplyTo == data:commentLevel1.id'>
<div class='level2'>
<div class='comment-header'>
<span class='comment-avatar'><img expr:src='resizeImage(data:commentLevel2.authorPhoto.url, 35, "1:1")'/></span>
<span class='comment-author'><a expr:href='data:commentLevel2.authorUrl'><data:commentLevel2.author/></a></span>
<span class='comment-date' expr:title='data:commentLevel2.timestamp'><data:commentLevel2.timestamp/></span>
</div>
<div class='comment-content'>
<data:commentLevel2.body/>
</div>
</div>
</b:if>
</b:loop>
</div>
</b:if>
</b:loop>
</div>
<script type='text/javascript'>
//<![CDATA[
$(".comment-reply").each(function() {
$(this).on("click", function(t) {
t.preventDefault(), $("#comment-editor")[0].src = $(this).attr("data-href"), $(this).parents(".level1").append($(".comments-form")[0])
})
});
//]]>
</script>
</b:if>
</div>
</b:includable>
Trong đó bạn cần đặc biệt lưu ý thằng này + "&skin=soho" (xuất hiện 2 lần).
- Nếu bạn xóa nó đi khung viết bình luận trở về v1.
- Nếu bạn thêm vào nhưng trong b:skin và <html chưa khai báo nó sẽ phụt ra error
- Nếu bạn đã update comment form lên v2 và sửa đúng tên skin (chữ màu đỏ) nó sẽ hiển thị đúng theo ý muốn (các skin bao gồm soho, contempo, emporio)
- Bạn nên nâng comment form lên v2 cho nó đồng bộ, xem bài viết Cập nhật blogger comment form lên version 2 thành công 100%
Như vậy đã hoàn thành xong phần định nghĩa hàm hiển thị khung viết bình luận và khung hiển thị bình luận, giờ là gọi ra sử dụng
Tìm đoạn mã
<b:include cond='data:view.isSingleItem' data='post' name='commentPicker'/>
và sửa thành
<b:include cond='data:view.isSingleItem' data='post' name='hung1001Comments'/>
Bạn có thể thoải mái thay đổi id của thẻ includable, miễn sao nó là duy nhất và định nghĩa như nào thì gọi đúng như vậy
Do định nghĩa và gọi hàm sử dụng bằng 1 thẻ hoàn toàn khác nên bạn yên tâm có thể quay về hệ thống bình luận cũ bất kì lúc nào
Với widget Blog1 v1
Định nghĩa 1 thẻ b:includable
<b:includable id='hung1001Comments' var='post'>
<div id='comments-holder'>
<div class='comments-form'>
<h4><i class='fas fa-pen-nib' /> <data:postCommentMsg/></h4>
<iframe allowtransparency='true' class='blogger-iframe-colorize blogger-comment-from-post' expr:src='"https://www.blogger.com/comment-iframe.g?blogID=" + data:blog.blogId + "&" + (data:view.isPost ? "postID" : "pageID") + "=" + data:post.id + "&skin=soho"' frameborder='0' id='comment-editor' name='comment-editor' width='100%' />
</div>
<b:if cond='data:post.numComments gt 0'>
<div class='comment-thread'>
<b:loop values='data:post.comments' var='commentLevel1'>
<b:if cond='!data:commentLevel1.inReplyTo'>
<div class='level1'>
<div class='comment-header'>
<span class='comment-avatar'><img expr:src='resizeImage(data:commentLevel1.authorPhoto.url, 35, "1:1")'/></span>
<span class='comment-author'><a expr:href='data:commentLevel1.authorUrl'><data:commentLevel1.author/></a></span>
<span class='comment-date' expr:title='data:commentLevel1.timestamp'><data:commentLevel1.timestamp/></span>
</div>
<div class='comment-content'>
<data:commentLevel1.body/>
</div>
<div class='comment-action'>
<a class='comment-reply' expr:data-href='"https://www.blogger.com/comment-iframe.g?blogID=" + data:blog.blogId + "&" + (data:view.isPost ? "postID" : "pageID") + "=" + data:post.id + "&parentID=" + data:commentLevel1.id + "&skin=soho"' href='javascript:void(0)'>REPLY</a>
</div>
<b:loop values='data:post.comments' var='commentLevel2'>
<b:if cond='data:commentLevel2.inReplyTo == data:commentLevel1.id'>
<div class='level2'>
<div class='comment-header'>
<span class='comment-avatar'><img expr:src='resizeImage(data:commentLevel2.authorPhoto.url, 35, "1:1")'/></span>
<span class='comment-author'><a expr:href='data:commentLevel2.authorUrl'><data:commentLevel2.author/></a></span>
<span class='comment-date' expr:title='data:commentLevel2.timestamp'><data:commentLevel2.timestamp/></span>
</div>
<div class='comment-content'>
<data:commentLevel2.body/>
</div>
</div>
</b:if>
</b:loop>
</div>
</b:if>
</b:loop>
</div>
<script type='text/javascript'>
//<![CDATA[
$(".comment-reply").each(function() {
$(this).on("click", function(t) {
t.preventDefault(), $("#comment-editor")[0].src = $(this).attr("data-href"), $(this).parents(".level1").append($(".comments-form")[0])
})
});
//]]>
</script>
</b:if>
</div>
</b:includable>
Phần skin tương tự như phần Blog1 v2
Cuối cùng là gọi ra để sử dụng
Tìm đoạn mã
<b:include cond='data:blog.pageType in {"static_page","item"}' data='post' name='comment_picker'/>
và sửa thành
<b:include cond='data:blog.pageType in {"static_page","item"}' data='post' name='hung1001Comments'/>
Lưu mẫu lại và kiểm tra thành quảChưa đến 3 dòng js đã xây dựng xong hệ thống bình luận phân cấp, rất ngầu đúng không ! với phương pháp này thì kể cả những người khó tính nhất cũng khó lòng mà không sử dụng lại blogger comment được
Như vậy bạn có thể thấy, chỉ cần chịu khó mày mò tìm hiểu về blogger code bạn có thể làm được tất cả những gì mình muốn.
Để lại bình luận nếu bạn gặp khó khăn và chúc thành công !
1. Không vi phạm luật pháp nước CHXHCN Việt Nam
2. Không vi phạm thuần phong mỹ tục Việt Nam
3. Không bàn luận vấn đề liên quan đến tôn giáo, chính trị
4. Không đả kích, chửi bới hay đưa ra những lời nói không phù hợp với mục tiêu của website
5. Không bình luận với mục đích quảng cáo, trao đổi, mua bán
6. Khuyến khích sử dụng Tiếng Việt có dấu, hạn chế sử dụng tiếng lóng, viết tắt
7. Khi cần sự trợ giúp, vui lòng miêu tả chi tiết lỗi và để lại link đính kèm, tránh nói chung chung gây mất thời gian cho đôi bên