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对gzip文件或者字符串解压实例参考
Jul 25 PHP
PHP中is_file不能替代file_exists的理由
Mar 04 PHP
php cli换行示例
Apr 22 PHP
PHP函数分享之curl方式取得数据、模拟登陆、POST数据
Jun 04 PHP
php通过smtp邮件验证登陆的方法
May 11 PHP
浅谈PHP中静态方法和非静态方法的相互调用
Oct 04 PHP
php 计算两个时间相差的天数、小时数、分钟数、秒数详解及实例代码
Nov 09 PHP
php获取当前url地址的方法小结
Jan 10 PHP
php json相关函数用法示例
Mar 28 PHP
PHP迭代与递归实现无限级分类
Aug 28 PHP
PHP实现的最大正向匹配算法示例
Dec 19 PHP
php中的钩子理解及应用实例分析
Aug 30 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/05 新手入门
orm获取关联表里的属性值
2016/04/17 PHP
php实现多站点共用session实现单点登录的方法详解
2019/09/18 PHP
PHP常用函数之获取汉字首字母功能示例
2019/10/21 PHP
JXTree对象,读取外部xml文件数据,生成树的函数
2007/04/02 Javascript
Javascript 强制类型转换函数
2009/05/17 Javascript
JQuery扩展插件Validate 2通过参数设置验证规则
2011/09/05 Javascript
JS中的public和private对象,即static修饰符
2012/01/18 Javascript
JavaScript中的函数的两种定义方式和函数变量赋值
2014/05/12 Javascript
当滚动条滚动到页面底部自动加载增加内容的js代码
2014/05/13 Javascript
Angular.js与Bootstrap相结合实现手风琴菜单代码
2016/04/13 Javascript
微信小程序 二维码canvas绘制实例详解
2017/01/06 Javascript
原生js实现焦点轮播图效果
2017/01/12 Javascript
在Vue mounted方法中使用data变量详解
2019/11/05 Javascript
JavaScript原型式继承实现方法
2019/11/06 Javascript
jQuery实现图片切换效果
2020/10/19 jQuery
详解JavaScript类型判断的四种方法
2020/10/21 Javascript
Python实现的数据结构与算法之双端队列详解
2015/04/22 Python
Python全排列操作实例分析
2018/07/24 Python
浅谈python 导入模块和解决文件句柄找不到问题
2018/12/15 Python
初探利用Python进行图文识别(OCR)
2019/02/26 Python
Python3 pandas 操作列表实例详解
2019/09/23 Python
numpy按列连接两个维数不同的数组方式
2019/12/06 Python
解决Keras中CNN输入维度报错问题
2020/06/29 Python
Python:__eq__和__str__函数的使用示例
2020/09/26 Python
在html5的Canvas上绘制椭圆的几种方法总结
2013/01/07 HTML / CSS
澳大利亚最受欢迎的超级商场每日优惠:Catch
2020/11/17 全球购物
什么叫应用程序域?什么是托管代码?什么是强类型系统?什么是装箱和拆箱?什么是重载?CTS、CLS和CLR分别作何解释?
2012/05/23 面试题
2014年教师业务学习材料
2014/05/12 职场文书
公司授权委托书样本
2014/09/15 职场文书
村干部群众路线整改措施思想汇报
2014/10/12 职场文书
银行贷款收入证明
2014/10/17 职场文书
会计电算化实训报告
2014/11/04 职场文书
厉行节约工作总结
2015/08/12 职场文书
MySQL创建管理子分区
2022/04/13 MySQL
MySQL中的 inner join 和 left join的区别解析(小结果集驱动大结果集)
2023/05/08 MySQL