使用thymeleaf模板實現博客評論的異步刷新


使用thymeleaf模板實現博客評論的異步刷新

最簡單的一個要求:用戶可以在博客下面進行評論,然后評論后點擊提交后直接上傳到數據庫,並且局部刷新
這是前端頁面的展示,使用的semanticUI進行構造出來的模型,另外semanticUi已經不再更新了。
進入重點:如果想要進行局部刷新,使用fragment標簽進行更新,如下第二行可以看到將這一塊的所有信息都給包裹起來。

		<div id="comment-container" class="ui teal segment">
            <div th:fragment="commentList">
                <div class="ui threaded comments" style="max-width: 100%">
                    <h3 class="ui dividing header">評論</h3>
                    <div class="comment"  th:each="comment : ${comments}">
                        <a class="avatar">
                            <img src="https://unsplash.it/100/100?image=1005" th:src="@{${comment.avatar}}">
                        </a>
                        <div class="content" >
                            <a class="author" >
                                <span th:text="${comment.nickname}">Matt</span>
                                <div class="ui mini basic teal left pointing label m-padded-mini" th:if="${comment.adminComment}">
                                    博主
                                </div>
                            </a>
                            <div class="metadata">
                                <span class="date" th:text="${#dates.format(comment.createTime,'yyyy-MM-dd HH:mm')}">Today at 5:42PM</span>
                            </div>
                            <div class="text" th:text="${comment.content}">
                                How artistic!
                            </div>
                            <div class="actions">
                                <a class="reply" data-commentid="1" data-commentnickname="Matt" th:attr="data-commentid=${comment.id},data-commentnickname=${comment.nickname}" onclick="reply(this)">回復</a>
                            </div>
                        </div>

                        <!--第二層-->
                        <div class="comments" th:if="${#arrays.length(comment.replyComments)}>0">
                            <div class="comment"  th:each="reply : ${comment.replyComments}">
                                <a class="avatar">
                                    <img src="https://unsplash.it/100/100?image=1005" th:src="@{${reply.avatar}}">
                                </a>
                                <div class="content" >
                                    <a class="author" >
                                        <span th:text="${reply.nickname}">小紅</span>&nbsp;
                                        <div class="ui mini basic teal left pointing label m-padded-mini" th:if="${reply.adminComment}">
                                            博主
                                        </div>
                                        <span th:text="|@ ${reply.parentComment.nickname}|" class="m-teal">@ 小白</span>
                                    </a>
                                    <div class="metadata">
                                        <span class="date" th:text="${#dates.format(reply.createTime,'yyyy-MM-dd HH:mm')}">Today at 5:42PM</span>
                                    </div>
                                    <div class="text" th:text="${reply.content}">
                                        How artistic!
                                    </div>
                                    <div class="actions">
                                        <a class="reply" data-commentid="1" data-commentnickname="Matt" th:attr="data-commentid=${reply.id},data-commentnickname=${reply.nickname}" onclick="reply(this)">回復</a>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

        </div>

這里是提交表單的所有內容,由於評論是一個嵌套的類,即一個評論可以有多個評論,一層層的嵌套下來,在這里需要注意的是,使用springdatajpa的過程中,盡量避免使用Lombok插件中的@Data進行注解類,它會直接產生所有屬性的toString,如果使用了,會報出stackoverflow異常,原因是你一直調用的toString方法,一直遞歸下去,導致棧溢出。最簡便的方法就是破壞toString方法中的輸出該類的信息,在這里就是不要輸出Comment的信息。


提交評論信息的同時,需要設置一個字段證明是新提交的信息而不是回復別人的信息。<input type="hidden" name="parentComent.id" value="-1">這段代碼就是實現這個功能,如果是評論博客而不是回復別人的信息,則直接將parentComent.id設置成-1,然后在后端進行判斷如果是-1則是新評論。

        <div id="comment-form" class="ui form">
            <input type="hidden" name="blog.id" th:value="${blog.id}">
            <input type="hidden" name="parentComent.id" value="-1">
            <div class="field">
                <textarea name="content" placeholder="請輸入評論信息..."></textarea>
            </div>
            <div class="fields">
                <div class="field m-mobile-wide m-margin-bottom-small">
                    <div class="ui left icon input">
                        <i class="user icon"></i>
                        <input type="text" name="nickname" placeholder="姓名" th:value="${session.user}!= null ? ${session.user.nickName}">
                    </div>
                </div>
                <div class="field m-mobile-wide m-margin-bottom-small">
                    <div class="ui left icon input">
                        <i class="mail icon"></i>
                        <input type="text" name="email" placeholder="郵箱" th:value="${session.user}!= null ? ${session.user.email}">
                    </div>
                </div>
                <div class="field  m-margin-bottom-small m-mobile-wide">
                    <button id="commentpost-btn" type="button" class="ui teal button m-mobile-wide"><i class="edit icon"></i>發布</button>
                </div>
            </div>

        </div>

js部分:

$(function () {
    //當頁面加載完成之后,需要把評論都給加載出來
    $("#comment-container").load(/*[[@{/comments/{id}(id=${blog.id})}]]*/"comments/6");
});

$("#commentpost-btn").click(function () {
    let boo=$('.ui.form').form('validate form');
    if (boo){
        postData();
        console.log('校驗成功');
    }else{
        console.log('校驗失敗');
    }
});
function postData(){
    $("#comment-container").load(/*[[@{/comments}]]*/"",{
        "parentComment.id":$("[name='parentComent.id']").val(),
        "blog.id":$("[name='blog.id']").val(),
        "nickname":$("[name='nickname']").val(),
        "email":$("[name='email']").val(),
        "content":$("[name='content']").val()
    },function (responseTxt,statusTxt,xhr) {
        clearContent();
        //滾動到最上面的評論

    })
}
function clearContent(){
    $("[name='content']").val('');
    $("[name='parentComent.id']").val(-1);
    $("[name='content']").attr("placeholder","請輸入評論信息...");
}

function reply(obj) {
    let commentId=$(obj).data('commentid');
    let nickNickname=$(obj).data('commentnickname');
    $("[name='content']").attr("placeholder","@"+nickNickname).focus();
    $("[name='parentComent.id']").val(commentId);
    $(window).scrollTo($("#comment-form"),500);
}

以上着重講下異步的過程:
commentpost-btn是提交按鈕的id,有一個點擊事件,點擊后進行提交 postData()方法,然后找到div的id為comment-container的標簽進行重新加載,加載的數據源為

/*[[@{/comments}]]*/

也就是找到controller層的url進行提交數據,然后將表單中的數據進行傳遞給后台,后台進行處理:

@PostMapping("/comments")
    public String post(Comment comment, HttpSession session){
        Long blogId = comment.getBlog().getId();
        comment.setBlog(blogService.getBlog(blogId));
        User user=(User)session.getAttribute("user");
        if (user!=null){
            comment.setAvatar(user.getAvatar());
            comment.setAdminComment(true);
           /* comment.setNickname(user.getNickName());*/
        }else{
            comment.setAvatar(avatar);
        }
        commentService.saveComment(comment);
        return "redirect:/comments/" + blogId;
    }

提交后在重定向給獲取所有評論的controller的url:

@GetMapping("/comments/{blogId}")
    public String comments(@PathVariable Long blogId, @NotNull Model model){
        model.addAttribute("comments",commentService.listCommentByBlogId(blogId));
        return "blog :: commentList";
    }

這里將所有的數據全部返回給blog頁面的commentList的fragment。
到此,異步刷新結束。

$(function () {
    //當頁面加載完成之后,需要把評論都給加載出來
    $("#comment-container").load(/*[[@{/comments/{id}(id=${blog.id})}]]*/"comments/6");
});

這段代碼的意思是黨頁面加載完成之后,將所有的評論都加載出來。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM