天天看點

評論回複功能的實作

評論回複功能的實作

最後的效果圖如上,大家不難發現這個回複的想法和知乎的回複模式差不多(因為我就是照着那個思路實作的 :) ),隻是這裡少實作了檢視對話的功能。下面說說我實作這個過程中遇到的一些困難。

首先講講我的資料庫的實作:

評論回複功能的實作

RId指的是每個評論的唯一id,這個R取得是review(評論)的意思

RTId指的是每條文章的id

RRId指的是被回複的評論的id,如果有就是其id,無為0

ROwnerName指的是此條評論的人的名字

RTargetName指的是被回複的人的名字,可空

RComments指的是評論的内容

RTime指的是評論的時間

(1)如何實作點選圖中的“回複”按鈕,在評論下方就彈出一個輸入框。

這個很好實作,主要涉及到的就是一些js的知識。

那麼,到底該怎麼實作點選“回複”,就在這個評論下方彈出一個輸入框而不是在其他的輸入框下彈出呢?

我們首先得給這個輸入框所在的div配置設定一個唯一的id,這裡我們可以使用評論的RId。

然後再給回複按鈕添加監聽函數,也就是設定其onclick屬性,傳入的參數就是輸入框的id。每當點選按鈕的時候,都改變輸入框所在div的display屬性

<button type="button" class="btn btn-secondary" onclick="hide('#{specificReview.RId}')">回複</button>  <br />
<p class="cContent">#{specificReview.RComments}</p>   <!--每個人回複的評論 -->  <br />

<div class="comment-edit" id="#{specificReview.RId}" style=" display: none;">
    <h:inputTextarea id="doubleComments"
                     class="form-control edit"
                     value="#{comment.RDComments}"                                
                     />
    <!--<h:message for="doubleComments" style="color:red"/>-->
    <div class="preview">
        <div class="buttons">
            <h:commandButton immediate="true" class="btn btn-secondary" rendered="#{!login.isLogin()}" value="評論前請先登入" action="#{navBean.login}" />
            <h:commandButton id="submitButton" rendered="#{login.isLogin()}" actionListener="#{discuss.setTopic(discuss.topic)}"  action="#{comment.storeIntoDB(discuss.topic.TId, specificReview.RId, login.userName, specificReview.ROwnerName)}" class="btn btn-primary post broadcast" value="回複"/>                
        </div>
    </div>
</div>
           

下面是javascript的代碼

<script>
        function hide(a) {
            if (document.getElementById(a).style.display !== 'none')
            {
                document.getElementById(a).style.display = 'none';
            }
            else
            {
                document.getElementById(a).style.display = '';
            }
        }
    </script>
           

可能有的猿友會疑惑那些 h: 和 #{} 是什麼東西。

這個h:是JSF架構下的元件(應該不影響閱讀吧,感覺和 HTML 的元素差不多),#{}是EL表達式。

(2)我們可以看到,有那麼多輸入框(隻是很多的display都是none,并沒有顯示)。那麼如何確定擷取到的輸入框的值恰巧是我們評論的輸入框的值呢?

我們都不難想到使用EL表達式來取值,也就是上面代碼中的<h:inputTextArea value="#{comment.RDComments}">

但是大家可能會遇到下面這個問題:在點選“評論”按鈕時,相當于送出表單,而這裡就會預設将你回複的評論下面的所有的<h:inputTextArea>(也就是我們的輸入框)中的value=#{comment.RDComments}執行一遍,這就導緻了我們擷取的評論值總是為空的情況。

那麼該怎麼解決這個情況呢?

其實很簡單,就是在set函數中判斷一下,如果擷取的值為空,就不指派。

public void setRDComments(String RDComments) {
        if (RDComments.length() > 0) {
            this.RDComments = RDComments;
        }
    }
           

(3)如何實作評論判空,我有兩個想法

1. 點選“評論”按鈕會在其下面彈出唯一一個提示框,提示内容是“評論不能為空”。

2.評論為空時,将評論按鈕disabled掉,這個給輸入框添加onchange函數就行,在函數裡使用getElementById擷取到輸入框的value,為空則disabled。

無論哪個想法,都繞不開給這個輸入框配置設定一個唯一的id,因為我好像并沒有找到擷取到一個div的element,然後再擷取其間的其他元素的js方法。說的有點繞

<div id="onlyOne">
  <input name="inputText" type="text" />
  <button name="submitButton" type="button">回複</button>
</div>
           

就是我知道這個div的id是"onlyOne",我能不能通過document.getElementById("onlyOne"),然後通過某種方法得到這個div中name為inputText或者為submitButton的元件的value呢?希望有路過的猿友能提示一下到底有沒有這樣一種方法。

<2020-05-13> 這個是可以的,我随手搜了一下,感覺 https://stackoverflow.com/a/5753895/10315163 這個就很不錯。

先說一下,其實我并沒有實作這個功能,隻有幾點關于給輸入框配置設定唯一id的想法。

沒實作的原因是在JSF架構下,其元件的id是變的(這個我就十分不了解)。

評論回複功能的實作

就像上面這個圖中的id,前面的那個j_idt157怎麼搞都搞不掉,後面那個10指的是這個頁面第幾個輸入框(這個是自動生成的,0是第1個,10就是第11個),最後面的doubleComments才是設定的id。

為了讓這個輸入框的id唯一,我嘗試了一個組合id的方法:

<div class="comment-edit" id="#{specificReview.RId}Div" style=" display: none;">
    <h:inputTextarea id="#{specificReview.RId}doubleComments"
                     class="form-control edit"
                     value="#{comment.RDComments}"                                
                     />
    <!--<h:message for="doubleComments" style="color:red"/>-->
    <div class="preview">
        <div class="buttons">
            <h:commandButton immediate="true" class="btn btn-secondary" rendered="#{!login.isLogin()}" value="評論前請先登入" action="#{navBean.login}" />
            <h:commandButton id="submitButton" rendered="#{login.isLogin()}" actionListener="#{discuss.setTopic(discuss.topic)}"  action="#{comment.storeIntoDB(discuss.topic.TId, specificReview.RId, login.userName, specificReview.ROwnerName)}" class="btn btn-primary post broadcast" value="回複"/>                
        </div>
    </div>
</div>
           

就是将id擴充一下,将原來的div的id改為"#{specificReview.RId}Div"(這樣親測有效),然後把輸入框的id擴充為"#{specificReview.RId}doubleComments",然而這樣并沒有啥用,這個輸入框的id依然是系統自己給配置設定的。

然而,我依舊不信邪,既然div能實作組合id,那你這個輸入框為啥不行,然後我就把這個輸入框的id設定為"#{specificReview.RId}",然後它卻報錯了,報錯原因是id不能為空。

不過我還有一個想法,就是不使用div布局了,改用table布局。給這個table配置設定唯一id為"#{specificReview.RId}",然後我們就有一個document.getElementById("tableId").rows[id].cells[1].innerText;來擷取到其下的<td>的值。不過我沒有具體了解這個js方法,能不能實作我也不能保證。

如果有猿友按照這個想法實作了,能不能勞煩通知我一聲,畢竟我也想知道這玩意能不能成。

(4)如何擷取到被回複的人的評論的id

這個可以通過添加函數action或者actionListener實作,然後将這個id作為調用函數的參數傳進去,在調用的函數裡儲存這個id。

當然實作類似的回複功能的方法有很多,我的這個隻能算是其中的比較基礎的一個。我在檢視知乎評論的頁面源碼的時候,好像還沒有發現知乎的評論輸入框都有一個id之類的,這也是讓我很困惑的地方。

<2020-05-13> 這個東西是我好久以前做的,當時我們小組連版本管理都沒有(我也不知道這個概念 XD),改完東西都是通過 U 盤拷貝來拷貝去的。依稀記得每次交換完最新代碼我都是用類似 project1 等名稱來命名那個檔案夾,當時是清楚啥是啥,現在回去看都無法确定哪個是最新的。現在回頭看來真的是感慨萬千。

 <2020-05-13> 我對這個項目依稀的記憶是基于 JSF 的,然後還有 Java Bean,企業 Bean 什麼的,伺服器是 Glassfish(至于為什麼不是 tomcat,我姑且不知道),IDE 是 Netbeans。這些都是個什麼東西我早就忘的一幹二淨了,就連怎麼運作這個項目也不記得了。剩下的隻是項目檔案夾下 12 的無意義的檔案,和這篇記錄當時自己颠簸的文章。還有最上面那個示範的 GIF 裡回複後自動回到頂部的奇怪 bug。是以源碼是不會提供了...,而且隻要思路清晰,寫出代碼是沒有問題的。(這個觀念是我最近看完《如何閱讀一本書》後和自己經曆對比後堅信的,書中說“一個人如果說他知道他在想些什麼,卻說不來,通常是他其實并不知道他自己在想些什麼。”)

<2020-05-13> 剛剛看到了有人分享 MIT 的 [The Missing Semester of Your CS Education](https://missing.csail.mit.edu/) 這個課程,想到了自己一直不願意直面的這篇文章,也想到了前幾個月無意中逛到的幾個人 ice1000、ibug...,想起了龍應台的目送:“你和他的緣分就是今生今世不斷地在目送他的背影漸行漸遠。你站在小路的這一端,看着他逐漸消失在小路轉彎的地方,而且,他用背影默默地告訴你,追不上。”(有改)。

繼續閱讀