做一個群組聊天頁面


要做個群組聊天的頁面,參考微信的web版本,大致就是分為左右兩列,左邊是群組列表,右邊是群組中的對話

示例圖如下:

 

這個頁面風格是使用ACE做的,再次嘖嘖下,ACE真TMD強大,這個頁面的風格很招人喜歡。

 

做這個頁面剛開始的時候我走了彎路,初步想的是使用iframe,左側群組聊天頁面是頁面加載的,右側的群組對話框是個iframe。然后點擊左側的任意一個群組,右側的對話iframe就修改src,然后更新對話的時候也超簡單,直接iframe重新加載一下就ok了。

但是呢,后來發現,我這樣需要寫的controller反而更多,一個iframe的controller,一個頁面本身的controller,然后在兩個iframe需要傳遞一些東西,特別是群組id。最大的困難就是更新,當我在iframe中發了一條消息之后,iframe中的條目能很快更新,但是外面的頁面(由於是使用輪詢)就沒辦法及時更新了。

后來總結了下,我整個頁面就使用最統一的方式,html+jsonp的形式,使用一個頁面controller,然后每個行為觸發一個jsonp,整體做下來,結果就是js量極速增大。但是,不算壞事。

 

頁面邏輯是這樣:

首先頁面初始加載群組列表

其次點擊群組名稱,同步加載出現右側的對話框。注意這里是使用同步加載。因為從用戶體驗上,如果使用異步,點擊了群組卻沒有出現對話框,會有bug的感覺。jquery的ajax是有提供jsonp和同步調用的:

代碼:

$("[name=talk_talk]").click(function(event){
    event.preventDefault();

    var target = event.target;
    var mgid = $(target).attr("data-mgid");
    var action = "http://api.test/group/messageList"
    var params = "mgid=" + mgid;

    $.ajax({
        type: "get",
        dataType: "jsonp",
        async:false,
        url: action,
        data: params,
        jsonp: 'callback',
        jsonpCallback: 'callback231',
        success: function(data) {
            if (data.msg == 'ok') {
                var messages = data.messages;
                var users = data.users;
                var message_contents = '';
                for(var i=0; i< messages.length; i++) {
                    var message = messages[i];
                    var sid = message.sid;
                    var sender = users[sid];
                    message.sender = sender;
                    message_content = getDialogHTML(message);
                    message_contents = message_contents + message_content;
                }    
                $("#messages_show").html(message_contents);
                $("#messages_show").attr("cur_mgid", mgid);
                $("#group_unreadflag_" + mgid).hide();
                $("#widget-box-dialog").show();
            }
        }
    });
});

這里的ajax的dataType設置為jsonp表示是個jsonp請求,加上后面的jsonp和jsonpCallback,表示調用的時候我傳遞的請求帶上了callback=callback231。

這里的jsonpCallback也是可以不寫的,但是如果不寫jquery會使用形如:callback_321342_324123這樣的函數名來替換。但是我希望服務器端使用白名單機制來控制callback只能是字母和數字(Yii):

if (!empty($callback) && ctype_alnum($callback)) {
    echo "{$callback}(" . CJSON::encode($ret) . ")";
    Yii::app()->end();
}

所以我就手動設置了callback函數。相關的安全考慮我記得以前有一篇文章寫過:http://www.cnblogs.com/yjf512/p/3222269.html

ajax的默認是異步的,所以要設置同步的話需要設置async:false。

 

接着就是輪詢函數

服務端有個jsonp接口能根據我返回的最新時間,返回這個時間后我收到的所有群組消息。

代碼幾乎同上,不同的就是這個行為應該且必須是異步的。然后做兩個事情:一件事情是如果左側的群組有新消息,設置一個標志表示有新消息。另一個事情是如果右側的對話顯示的是當前這個群組的對話,就增加一個最新的消息放到上面。

 

然后是發送消息,基本同上。

好吧,主要還是秀一下ACE模板,看的爽。


免責聲明!

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



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