Ajax PHP JavaScript MySQL实现简易无刷新在线聊天室


Posted in PHP onAugust 17, 2016

为更好的运用这两天学到的Ajax的相关的知识,就做了个简单的在线网络聊天室。

Ajax PHP JavaScript MySQL实现简易无刷新在线聊天室

思路

实现聊天室,基本上就是通过Ajax来传递数据,让PHP来实现对数据的差入和查找,再交给前端JavaScript实现页面的更新,达到即时聊天的功能。

消息显示区

消息显示区就是一个DIV块,我们会借助Ajax获取到服务器端信息之后,使用JavaScript来更新页面。

<h3>消息显示区</h3>
<div id="up">
</div>
<hr />

发消息

发消息模块,其实说白了,就是向服务器上插入数据的过程,也是属于比较简单的。

<h3>发言栏</h3>
  <div id="bottom">
    <form action="./chatroom_insert.php">
      <div id="chat_up">
        <span>颜色</span>
        <input type="color" name="color"/>
        <span>表情</span>
        <select name="biaoqing">
          <option value="微笑地">微笑地</option>
          <option value="猥琐地">猥琐地</option>
          <option value="和蔼地">和蔼地</option>
          <option value="目不转睛地">目不转睛地</option>
          <option value="傻傻地">傻傻地</option>
        </select>
        <span>聊天对象</span>
        <select name="receiver">
          <option value="">所有的人</option>
          <option value="老郭">老郭</option>
          <option value="小郭">小郭</option>
          <option value="大郭">大郭</option>
        </select>
      </div>
      <div id="chat_bottom">
        <textarea id="msg" name="msg" style="width:380px;height:auto;"></textarea>
        <input type="button" value="发言" onclick="send()" />
        发言:<span id="result"></span>
      </div>
    </form>
  </div>

板块

下面开始使用代码来实现相关的业务逻辑。

消息显示

我们的思路就是每隔一段时间,客户端向服务器发送请求,轮询获得最新的数据。

<script>

function showmessage(){
  var ajax = new XMLHttpRequest();
  // 从服务器获取并处理数据
  ajax.onreadystatechange = function(){
    if(ajax.readyState==4) {
      //alert(ajax.responseText); 
      // 将获取到的字符串转换成实体
      eval('var data = '+ajax.responseText);
      // 遍历data数组,把内部的信息一个个的显示到页面上
      var s = "";
      for(var i = 0 ; i < data.length;i++){
        data[i];
        s += "("+data[i].add_time+") >>>";
        s += "<p style='color:"+data[i].color+";'>";  
        s += data[i].sender +" 对 " + data[i].receiver +"  "+ data[i].biaoqing+"说:" + data[i].msg;
        s += "</p>";

      }
      // 开始向页面时追加信息
      var showmessage = document.getElementById("up");
      showmessage.innerHTML += s;

    }
  }
  ajax.open('get','./chatroom.php');
  ajax.send(null);  

}

// 更新信息的执行时机
window.onload = function(){
  //showmessage();  
  // 制作轮询,实现自动的页面更新
  setInterval("showmessage()",3000);
}
</script>

里面比较重要的就是setInterval函数的使用,以此来实现间隔性的触发请求事件。 

消息发送

关于消息发送,通过表单形式发给服务器即可。我们这里使用了目前Html5的一个最新的技术,FormData,一般来说目前的主流的现代浏览器都是支持这一技术了。使用FormData我们可以方便的获取一个表单的数据。

注意: FormData收集表单数据的时候是以键值对的形式搜集的,所以对应的表单项一定要有name属性,否则表单将收集不到该项的数据值。

<script>
  function send(){
    // 向服务器差入相关的数据
    var form = document.getElementsByTagName('form')[0];
    var formdata = new FormData(form);
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
      if(xhr.readyState==4) {
        //alert(xhr.resposneText);
        document.getElementById("result").innerHTML = xhr.responseText;
        setTimeout("hideresult()",2000);
      }
    }
    xhr.open('post','./chatroom_insert.php');
    xhr.send(formdata);
    document.getElementById("msg").value="";
    //return false;
  }

  // 2秒后实现提示信息的消失
  function hideresult(){
    document.getElementById('result').innerHTML = "";  
  }
</script>

值得深思的是:setTimeout函数实现的功能。在得到服务器端的反馈信息之后,及时的更新到发送按钮后面,给用户一个很好的体验。

优化

做完这里基本上就可以实现聊天了。但是实现的效果会非常的不好,主要是有以下几点。
 •没有滚动显示,每次都得手动的查看最新消息。
 •获取到的数据有很多的重复数据,既浪费流量,也不方便查看信息。 

显示非重复性的数据

对于显示重复性的数据,这是因为我们没有使用where语句,而好似每次都获取到所有的数据了。试想一下,怎样才能获取到最新的数据呢?
而且对于不同的客户端都要照顾得到。

好莱坞原则:不要来找我,我会去找你

这也是很多软件开发理念的一个体现,让客户决定来获取什么数据,而不是服务器端一棍子打死。所以我们需要在客户端发送数据请求方面最优化。

<script>
// 记录当前获取到的id的最大值,防止获取到重复的信息
var maxId = 0;
function showmessage(){
  var ajax = new XMLHttpRequest();
  // 从服务器获取并处理数据
  ajax.onreadystatechange = function(){
    if(ajax.readyState==4) {
      //alert(ajax.responseText); 
      // 将获取到的字符串转换成实体
      eval('var data = '+ajax.responseText);
      // 遍历data数组,把内部的信息一个个的显示到页面上
      var s = "";
      for(var i = 0 ; i < data.length;i++){
        data[i];
        s += "("+data[i].add_time+") >>>";
        s += "<p style='color:"+data[i].color+";'>";  
        s += data[i].sender +" 对 " + data[i].receiver +"  "+ data[i].biaoqing+"说:" + data[i].msg;
        s += "</p>";
        // 把已经获得的最大的记录id更新
        maxId = data[i].id;
      }
      // 开始向页面时追加信息
      var showmessage = document.getElementById("up");
      showmessage.innerHTML += s;
      //showmessage.scrollTop 可以实现div底部最先展示
      // divnode.scrollHeight而已获得div的高度包括滚动条的高度
      showmessage.scrollTop = showmessage.scrollHeight-showmessage.style.height;
    }
  }
  ajax.open('get','./chatroom.php?maxId='+maxId);
  ajax.send(null);  

}

// 更新信息的执行时机
window.onload = function(){
  //showmessage();  
  // 制作轮询,实现自动的页面更新
  setInterval("showmessage()",3000);
}
</script>

优化显示

优化显示界面是必不可少的,没有人能够容忍发送一条数据之后还得手动的查看最新的消息。所以我们要设置一下显示区域的div。

加上滚动条

<style>
  #up {
    height:320px;
    width:100%;
    overflow:auto; 
  }
</style>

每次都显示最新消息

说白了就是让底部的div永远最先显示。

//showmessage.scrollTop 可以实现div底部最先展示
// divnode.scrollHeight而已获得div的高度包括滚动条的高度
showmessage.scrollTop = showmessage.scrollHeight-showmessage.style.height;

完整代码

前端代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ajax 聊天室</title>
<style>
  #up {
    height:320px;
    width:100%;
    overflow:auto; 
  }


</style>
<script>
// 记录当前获取到的id的最大值,防止获取到重复的信息
var maxId = 0;
function showmessage(){
  var ajax = new XMLHttpRequest();
  // 从服务器获取并处理数据
  ajax.onreadystatechange = function(){
    if(ajax.readyState==4) {
      //alert(ajax.responseText); 
      // 将获取到的字符串转换成实体
      eval('var data = '+ajax.responseText);
      // 遍历data数组,把内部的信息一个个的显示到页面上
      var s = "";
      for(var i = 0 ; i < data.length;i++){
        data[i];
        s += "("+data[i].add_time+") >>>";
        s += "<p style='color:"+data[i].color+";'>";  
        s += data[i].sender +" 对 " + data[i].receiver +"  "+ data[i].biaoqing+"说:" + data[i].msg;
        s += "</p>";
        // 把已经获得的最大的记录id更新
        maxId = data[i].id;
      }
      // 开始向页面时追加信息
      var showmessage = document.getElementById("up");
      showmessage.innerHTML += s;
      //showmessage.scrollTop 可以实现div底部最先展示
      // divnode.scrollHeight而已获得div的高度包括滚动条的高度
      showmessage.scrollTop = showmessage.scrollHeight-showmessage.style.height;
    }
  }
  ajax.open('get','./chatroom.php?maxId='+maxId);
  ajax.send(null);  

}

// 更新信息的执行时机
window.onload = function(){
  //showmessage();  
  // 制作轮询,实现自动的页面更新
  setInterval("showmessage()",3000);
}
</script>

</head>

<body style="background-color:silver">
<div id="main">
  <h3>消息显示区</h3>
  <div id="up">
  </div>
  <hr />
  <h3>发言栏</h3>
  <div id="bottom">
    <form action="./chatroom_insert.php">
      <div id="chat_up">
        <span>颜色</span>
        <input type="color" name="color"/>
        <span>表情</span>
        <select name="biaoqing">
          <option value="微笑地">微笑地</option>
          <option value="猥琐地">猥琐地</option>
          <option value="和蔼地">和蔼地</option>
          <option value="目不转睛地">目不转睛地</option>
          <option value="傻傻地">傻傻地</option>
        </select>
        <span>聊天对象</span>
        <select name="receiver">
          <option value="">所有的人</option>
          <option value="老郭">老郭</option>
          <option value="小郭">小郭</option>
          <option value="大郭">大郭</option>
        </select>
      </div>
      <div id="chat_bottom">
<script>
  function send(){
    // 向服务器差入相关的数据
    var form = document.getElementsByTagName('form')[0];
    var formdata = new FormData(form);
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
      if(xhr.readyState==4) {
        //alert(xhr.resposneText);
        document.getElementById("result").innerHTML = xhr.responseText;
        setTimeout("hideresult()",2000);
      }
    }
    xhr.open('post','./chatroom_insert.php');
    xhr.send(formdata);
    document.getElementById("msg").value="";
    //return false;
  }

  // 2秒后实现提示信息的消失
  function hideresult(){
    document.getElementById('result').innerHTML = "";  
  }
</script>
        <textarea id="msg" name="msg" style="width:380px;height:auto;"></textarea>
        <input type="button" value="发言" onclick="send()" />
        发言:<span id="result"></span>
      </div>
    </form>
  </div>

</div>
</body>
</html>

 数据库表结构

mysql> desc message;
+----------+--------------+------+-----+---------+----------------+
| Field  | Type     | Null | Key | Default | Extra     |
+----------+--------------+------+-----+---------+----------------+
| id    | int(100)   | NO  | PRI | NULL  | auto_increment |
| msg   | varchar(255) | NO  |   | NULL  |        |
| sender  | varchar(30) | NO  |   | NULL  |        |
| receiver | varchar(30) | NO  |   | NULL  |        |
| color  | varchar(10) | YES |   | NULL  |        |
| biaoqing | varchar(10) | YES |   | NULL  |        |
| add_time | datetime   | YES |   | NULL  |        |
+----------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)

服务器端代码

<?php

// 获得最新的聊天信息
$conn = mysql_connect('localhost','root','mysql');
mysql_select_db('test');
mysql_query('set names utf8');

$maxId = $_GET['maxId'];

// 防止获取重复数据,本次请求的记录结果id要大鱼上次获得的id
$sql = "select * from message where id >"."'$maxId'";
$qry = mysql_query($sql);

$info = array();
while($rst = mysql_fetch_assoc($qry)){
  $info[] = $rst;
}


// 通过json格式给客户端提供数据
echo json_encode($info);


?>

总结与展望

总结

完整的小例子就是这样了。回顾一下,今天的收获有:
 •如何轮询获得数据,借助了setInterval函数
 •定时消失提示的数据,借助了setTimeout函数
 •如何获取最新数据:有客户端控制发送的maxId参数。
 •如何优化显示:overflow实现滚动效果;divnode.scrollTop控制显示底部特效 

展望
 •也许你会发现,客户端发送人是固定的,那就是因为咱们没有做用户登录。如果做了用户登录,我们的发送人就可以从Session里面动态的获取。这样也能更符合人们的主观感受。

 •界面做的比较烂,没有加美化效果。加上Bootstrap后效果应该会很棒。

 •手机适配效果不好,另外在WindowsPhone上面颜色控件不能正常的显示。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
用PHP的ob_start();控制您的浏览器cache!
Nov 25 PHP
php下实现伪 url 的超简单方法[转]
Sep 24 PHP
php 获取select下拉列表框的值
May 08 PHP
PHP设计模式 注册表模式(多个类的注册)
Feb 05 PHP
ajax取消挂起请求的处理方法
Mar 18 PHP
基于php的CMS中展示文章类实例分析
Jun 18 PHP
PHP进程通信基础之信号
Feb 19 PHP
php图像验证码生成代码
Jun 08 PHP
Laravel中日期时间处理包Carbon的简单使用
Sep 21 PHP
gearman中worker常驻后台,导致MySQL server has gone away的解决方法
Feb 27 PHP
PHP7 foreach() 函数修改
Mar 09 PHP
PHP7 新增常量
Mar 09 PHP
全面解析PHP验证码的实现原理 附php验证码小案例
Aug 17 #PHP
针对多用户实现头像上传功能PHP代码 适用于登陆页面制作
Aug 17 #PHP
总结PHP中数值计算的注意事项
Aug 14 #PHP
示例详解Laravel的注册重构
Aug 14 #PHP
PHP实现路由映射到指定控制器
Aug 13 #PHP
Yii2.0中的COOKIE和SESSION用法
Aug 12 #PHP
PHP Oauth授权和本地加密实现方法
Aug 12 #PHP
You might like
法国:浪漫之都的咖啡文化
2021/03/03 咖啡文化
PHP中的Session对象如何使用
2015/09/25 PHP
优化WordPress的Google字体以加速国内服务器上的运行
2015/11/24 PHP
使用PHP处理数据库数据如何将数据返回客户端并显示当前状态
2016/02/16 PHP
php抽象方法和抽象类实例分析
2016/12/07 PHP
Laravel核心解读之异常处理的实践过程
2019/02/24 PHP
JS验证控制输入中英文字节长度(input、textarea等)具体实例
2013/06/21 Javascript
js获取GridView中行数据的两种方法 分享
2013/07/13 Javascript
JS操作iframe里的dom(实例讲解)
2014/01/29 Javascript
JavaScript 定时器 SetTimeout之定时刷新窗口和关闭窗口(代码超简单)
2016/02/26 Javascript
JS中创建函数的三种方式及区别
2016/03/13 Javascript
JavaScript 不支持 indexof 该如何解决
2016/03/30 Javascript
Javascript删除指定元素节点的方法
2016/06/21 Javascript
微信小程序 require机制详解及实例代码
2016/12/14 Javascript
jQuery动态生成表格及右键菜单功能示例
2017/01/13 Javascript
JavaScript实现动态增删表格的方法
2017/03/09 Javascript
es6数据变更同步到视图层的方法
2019/03/04 Javascript
详解JavaScript中的强制类型转换
2019/04/15 Javascript
nuxt+axios实现打包后动态修改请求地址的方法
2020/04/22 Javascript
JavaScript进阶(四)原型与原型链用法实例分析
2020/05/09 Javascript
JavaScript中CreateTextFile函数
2020/08/30 Javascript
Centos 升级到python3后pip 无法使用的解决方法
2018/06/12 Python
python机器学习包mlxtend的安装和配置详解
2019/08/21 Python
Python中的list与tuple集合区别解析
2019/10/12 Python
Pycharm激活码激活两种快速方式(附最新激活码和插件)
2020/03/12 Python
Python的scikit-image模块实例讲解
2020/12/30 Python
pycharm 实现复制一行的快捷键
2021/01/15 Python
美体小铺奥地利官方网站:The Body Shop奥地利
2019/04/11 全球购物
利物浦足球俱乐部官方商店(美国):Liverpool FC US
2019/10/09 全球购物
艺术系应届生的自我评价
2013/10/19 职场文书
桥梁工程专业求职信
2014/04/21 职场文书
马丁路德金演讲稿
2014/05/19 职场文书
2014年远程教育工作总结
2014/12/09 职场文书
会议营销主持词
2015/07/03 职场文书
大学生军训心得体会5篇
2019/08/15 职场文书
JavaScript canvas实现流星特效
2021/05/20 Javascript