评论回复功能的实现



最后的效果图如上,大家不难发现这个回复的想法和知乎的回复模式差不多(因为我就是照着那个思路实现的 :) ),只是这里少实现了查看对话的功能(其实不是不能实现,只是最后不想做了 :) )。下面说说我实现这个过程中遇到的一些困难。


首先讲讲我的数据库的实现:


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框架下的组件(应该不影响阅读吧),#{}是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呢?希望有路过的猿友能提示一下到底有没有这样一种方法


先说一下,其实我并没有实现这个功能,只有几点关于给输入框分配唯一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方法,能不能实现我也不能保证。


emmm,如果有猿友按照这个想法实现了,能不能劳烦通知我一声,毕竟我也想知道这玩意能不能成。


(4)如何获取到被回复的人的评论的id

这个可以通过添加函数action或者actionListener实现,然后将这个id作为调用函数的参数传进去,在调用的函数里保存这个id。


当然实现类似的回复功能的方法有很多,我的这个只能算是其中的比较基础的一个。我在查看知乎评论的源码的时候,好像还没有发现知乎的评论输入框都有一个id之类的,这也是让我很困惑的地方。


猜你喜欢

转载自blog.csdn.net/sinat_41104353/article/details/80699631