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 8小时时间差的解决方法小结
Dec 22 PHP
让的PHP代码飞起来的40条小技巧(提升php效率)
Apr 12 PHP
PHP中CURL方法curl_setopt()函数的参数分享
Jan 19 PHP
php 模拟POST提交的2种方法详解
Jun 17 PHP
跟我学Laravel之配置Laravel
Oct 15 PHP
php以post形式发送xml的方法
Nov 04 PHP
PHP使用PDO操作数据库的乱码问题解决方法
Apr 08 PHP
常用PHP数组排序函数归纳
Aug 08 PHP
php结合ajax实现手机发红包的案例
Oct 13 PHP
laravel5.2实现区分前后台用户登录的方法
Jan 11 PHP
PHP常见过waf webshell以及最简单的检测方法
May 21 PHP
tp5.1 框架数据库常见操作详解【添加、删除、更新、查询】
May 26 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
解析阿里云ubuntu12.04环境下配置Apache+PHP+PHPmyadmin+MYsql
2013/06/26 PHP
PHP 下载文件时自动添加bom头的方法实例
2014/01/10 PHP
如何解决phpmyadmin导入数据库文件最大限制2048KB
2015/10/09 PHP
在WordPress中实现发送http请求的相关函数解析
2015/12/29 PHP
深入讲解PHP的对象注入(Object Injection)
2017/03/01 PHP
鼠标滑上去后图片放大浮出效果的js代码
2011/05/28 Javascript
表单元素与非表单元素刷新区别详细解析
2013/11/06 Javascript
jQuery jcrop插件截图使用方法
2013/11/20 Javascript
JavaScript函数使用的基本教程
2015/06/04 Javascript
jquery分隔Url的param方法(推荐)
2016/05/25 Javascript
Vue 仿百度搜索功能实现代码
2017/02/16 Javascript
Bootstrap 3 按钮标签实例代码
2017/02/21 Javascript
JS移动端/H5同时选择多张图片上传并使用canvas压缩图片
2017/06/20 Javascript
[js高手之路]HTML标签解释成DOM节点的实现方法
2017/08/31 Javascript
Angular2开发环境搭建教程之VS Code
2017/12/15 Javascript
微信小程序wx.navigateTo中events属性实现页面间通信传值,数据同步
2019/07/13 Javascript
[00:44]2016完美“圣”典 风云人物:Mikasa宣传片
2016/12/07 DOTA
跟老齐学Python之折腾一下目录
2014/10/24 Python
PyCharm 设置SciView工具窗口的方法
2019/01/15 Python
Python学习笔记基本数据结构之序列类型list tuple range用法分析
2019/06/08 Python
python打印文件的前几行或最后几行教程
2020/02/13 Python
python thrift 实现 单端口多服务的过程
2020/06/08 Python
keras Lambda自定义层实现数据的切片方式,Lambda传参数
2020/06/11 Python
使用python画出逻辑斯蒂映射(logistic map)中的分叉图案例
2020/12/11 Python
美国修容界大佬创建的个人美妆品牌:Kevyn Aucoin Beauty
2018/12/12 全球购物
SCHIESSER荷兰官方网站:德国内衣专家
2020/10/09 全球购物
如何配置、使用和清除Smarty缓存
2015/12/23 面试题
汽车技术服务与营销专业在籍生自荐信
2013/09/28 职场文书
自动化专业本科毕业生求职信
2013/10/20 职场文书
酒店办公室文员岗位职责
2013/12/18 职场文书
开学寄语大全
2014/04/08 职场文书
卖车协议书
2014/04/21 职场文书
食品安全工作方案
2014/05/07 职场文书
迎新生标语大全
2014/10/06 职场文书
表扬稿表扬信的格式及范文
2019/06/24 职场文书
SQL Server2019数据库备份与还原脚本,数据库可批量备份
2021/11/20 SQL Server