jQuery 进阶二
一、使用jQuery中的Ajax实现无刷新分页
1. 分页原理
php中查询所有数据的语句:
select * from 数据表
分页原理:
假设每一页显示 3 条数据,使用变量$pageSize
表示,即$pageSize=3
当前的页码从地址栏获取,如果地址栏存在p参数,就获取它,如果不存在p参数,默认是第1页,所以:
第一页:select * from 数据表 limit 0,3;
第二页:select * from 数据表 limit 3,3;
第三页:select * from 数据表 limit 6,3;
…
第 p页:select * from 数据表 limit ($p-1)*$pageSize,$pageSize;
2. 分页数据查询
<?php
//还是使用省市县三表
//连接数据库
$pdo = new PDO('mysql:host=localhost; dbname=test; charset=utf8;','root');
//定义变量
$pageSize = 3;
$p = $_GET['p']?$_GET['p']:1;
//$p = $_GET['p'] ?? 1;
//sql语句
$sql = "select * from sheng limit ".($p-1)*$pageSize.','.$pageSize;
//预处理sql语句
$stmt = $pdo->prepare($sql);
//执行sql语句
$stmt->execute();
//获取结果集
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
//格式化php格式
echo '<pre>';
//输出
print_r($data);
使用 postman 发送请求看看结果:
3. 输出数据、分页并实现分页的渲染
PHP
<?php
/* 获取数据表数据 */
//还是使用省市县三表
//连接数据库
$pdo = new PDO('mysql:host=localhost; dbname=test; charset=utf8;','root');
//定义变量
$pageSize = 3;
$p = $_GET['p']?$_GET['p']:1;
//$p = $_GET['p'] ?? 1;
//sql语句
$sql = "select * from sheng limit ".($p-1)*$pageSize.','.$pageSize;
//预处理sql语句
$stmt = $pdo->prepare($sql);
//执行sql语句
$stmt->execute();
//获取结果集
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
//格式化php格式
//echo '<pre>';
//输出
//print_r($data);
/* 制作分页页码 */
//上一页,小于1就不能继续上一页,否则就是按照$p-1来进行页数跳转
if($p<=1){
$prev = "<a href='javascript:void(0);'>上一页</a>";
}else{
$prev = "<a href='?p=".($p-1)."'>上一页</a>";
}
//下一页,获取数据表条数,向上取整
$sql_count = "select count(*) from sheng";
//预处理sql语句
$stmt = $pdo->prepare($sql_count);
//执行sql语句
$stmt->execute();
//获取总数
$count = $stmt->fetchColumn(); //总记录数
//向上取整
$maxPage = ceil($count/$pageSize);
if($p<$maxPage){
$next = "<a href='?p=".($p+1)."'>下一页</a>";
}else{
$next = "<a href='javascript:void(0);'>下一页</a>";
}
/* 处理,响应 */
$page = $prev.$next;
$res = [$data,$page];
echo json_encode($res);
?>
使用postman查看结果:
HTML
<!-- 渲染 -->
<h2 align="center">无刷新分页</h2>
<table border="1" cellspacing="0" cellpadding="2" width="600" align="center" rules="all">
<thead>
<tr>
<th>PID</th>
<th>Pcode</th>
<th>Pname</th>
</tr>
</thead>
<tbody>
<!-- 数据 -->
</tbody>
</table>
<p align="center">
<!-- 分页 -->
</p>
4. 无刷新分页获取第一页数据
使用jQuery中的Ajax进行请求,并将数据遍历到html中。
/* 获取第一页数据 */
$(function(){
$.get('page.php',{p:1},function(res){
/* 获取数据表数据 */
var data = res[0];
/* 获取分页 */
var page = res[1];
/* 遍历数据表数据,构建html */
var str = '';
$.each(data,function(i,val){
str+='<tr>';
str+='<td>'+val.PID+'</td>';
str+='<td>'+val.Pcode+'</td>';
str+='<td>'+val.Pname+'</td>';
str+='</tr>';
})
$('tbody').html(str);
$('p').html(page);
},'json')
});
看看效果:
5. 实现无刷新分页
要实现无刷新的分页,必须让a标签不能跳转才可以。所以将a标签的href属性值都写成javascript:void(0);
又因为,点击a标签的时候,必须知道你要请求哪一页的数据,所以在a标签上还必须体现出请求的页码。
修改PHP
再次后台查看html代码:
因此根据 pp 的值进行跳转:
原理:根据 pp 的值,发送Ajax请求,再次更新页面数据。
值得注意的是:<a>
是后期加载而来,绑定事件是需要使用 on 方法。
案例总体:
HTML
<!-- 渲染 -->
<h2 align="center">无刷新分页</h2>
<table border="1" cellspacing="0" cellpadding="2" width="600" align="center" rules="all">
<thead>
<tr>
<th>PID</th>
<th>Pcode</th>
<th>Pname</th>
</tr>
</thead>
<tbody>
<!-- 数据 -->
</tbody>
</table>
<p align="center">
<!-- 分页 -->
</p>
JavaScript
$(function(){
/* 获取第一页数据 */
$.get('page.php',{p:1},function(res){
/* 获取数据表数据 */
var data = res[0];
/* 获取分页 */
var page = res[1];
/* 遍历数据表数据,构建html */
var str = '';
$.each(data,function(i,val){
str+='<tr>';
str+='<td>'+val.PID+'</td>';
str+='<td>'+val.Pcode+'</td>';
str+='<td>'+val.Pname+'</td>';
str+='</tr>';
})
$('tbody').html(str);
$('p').html(page);
},'json');
/* 无刷新分页 */
//点击a 标签,获取对应的页的数据。因为a标签是后加载过来的,所以必须使用on事件
$(document).on('click','a',function(){
/* 获取pp的 value 值 */
var pp = $(this).attr('pp'); //获取标签的属性值
/* 再次发送请求 */
$.get('page.php',{p:pp},function(res){
/* 获取数据表数据 */
var data = res[0];
/* 获取分页 */
var page = res[1];
/* 遍历数据表数据,构建html */
var str = '';
$.each(data,function(i,val){
str+='<tr>';
str+='<td>'+val.PID+'</td>';
str+='<td>'+val.Pcode+'</td>';
str+='<td>'+val.Pname+'</td>';
str+='</tr>';
})
$('tbody').html(str);
$('p').html(page);
},'json');
})
});
PHP(page.php)
<?php
/* 获取数据表数据 */
//还是使用省市县三表
//连接数据库
$pdo = new PDO('mysql:host=localhost; dbname=test; charset=utf8;','root');
//定义变量
$pageSize = 3;
$p = $_GET['p']?$_GET['p']:1;
//$p = $_GET['p'] ?? 1;
//sql语句
$sql = "select * from sheng limit ".($p-1)*$pageSize.','.$pageSize;
//预处理sql语句
$stmt = $pdo->prepare($sql);
//执行sql语句
$stmt->execute();
//获取结果集
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
//格式化php格式
//echo '<pre>';
//输出
//print_r($data);
/* 制作分页页码 */
//上一页,小于1就不能继续上一页,否则就是按照$p-1来进行页数跳转
// if($p<=1){
// $prev = "<a href='javascript:void(0);'>上一页</a>";
// }else{
// $prev = "<a href='?p=".($p-1)."'>上一页</a>";
// }
if($p<=1){
$prev = "<a href='javascript:void(0);' pp='1'>上一页</a>";
}else{
$prev = "<a href='javascript:void(0);' pp='".($p-1)."'>上一页</a>";
}
//下一页,获取数据表条数,向上取整
$sql_count = "select count(*) from sheng";
//预处理sql语句
$stmt = $pdo->prepare($sql_count);
//执行sql语句
$stmt->execute();
//获取总数
$count = $stmt->fetchColumn(); //总记录数
//向上取整
$maxPage = ceil($count/$pageSize);
// if($p<$maxPage){
// $next = "<a href='?p=".($p+1)."'>下一页</a>";
// }else{
// $next = "<a href='javascript:void(0);'>下一页</a>";
// }
if($p<$maxPage){
$next = "<a href='javascript:void(0);' pp='".($p+1)."'>下一页</a>";
}else{
$next = "<a href='javascript:void(0);' pp='$maxPage'>下一页</a>";
}
/* 处理,响应 */
$page = $prev.$next;
$res = [$data,$page];
echo json_encode($res);
?>
效果:
二、跨域请求
1. 跨域请求的三种方法
与JavaScript相同,实现跨域请求的方法有:
- 使用代理的方法
- 使用cors方式实现请求(设置访问权限)
参考博客: https://blog.csdn.net/Errrl/article/details/104088491
- 使用JSONP技术
2. JSONP技术
Jsonp(JSON with Padding) 是 json 的一种"使用模式",通俗的讲,jsonp可以通过html标签中的src属性访问另外域的内容,可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
什么样的HTML标签有src属性:
-
img
-
script
-
iframe
实例:
www.ajaxtest.com:03kuayu.html
HTML
<input type="button" value="请求" id="btn">
javaScript
document.getElementById('btn').onclick = function(){
/* 创建一个script标签,因为script含有src属性 */
var scr = document.createElement('script');
scr.src = 'http://www.jstest.com/03kuayu.php';
document.body.appendChild(scr);
}
//创建一个函数接受响应数据
function fn(res){
console.log(res);
}
www.jstest.com:03kuayu.php
<?php
//echo "alert(123)";
//可以在php中echo js代码
//echo "fn()"; //告诉浏览器执行函数fn
$arr = [
['id'=>1,'name'=>'yaodao'],
['id'=>2,'name'=>'jack']
];
/* 响应数据,告诉浏览器调用函数输出数据 */
$res = json_encode($arr);
echo "fn($res)";
//在此调用函数fn,所以JavaScript中必须准备声明fn函数来接收数据
同样也可以将函数当作一个值进行传递。这样可以避免函数名不确认的情况。
修改JavaScript代码:
document.getElementById('btn').onclick = function(){
/* 创建一个script标签,因为script含有src属性 */
var scr = document.createElement('script');
scr.src = 'http://www.jstest.com/03kuayu.php?callback=fn';
document.body.appendChild(scr);
}
//创建一个函数接受响应数据
function fn(res){
console.log(res);
}
修改PHP代码:
<?php
//echo "alert(123)";
//可以在php中echo js代码
//echo "fn()"; //告诉浏览器执行函数fn
$arr = [
['id'=>1,'name'=>'yaodao'],
['id'=>2,'name'=>'jack']
];
/* 响应数据,告诉浏览器调用函数输出数据 */
$res = json_encode($arr);
/* 多一步,获取地址栏的参数 */
$fn = $_GET['callback'];
echo "$fn($res)";
//在此调用函数fn,所以JavaScript中必须准备声明fn函数来接收数据
3. jQuery 中的 Ajax 跨域请求
将jQuery Ajax请求中的第三个参数修改成 ‘jsonp’ 即可。
例如:
/* 方法一 */
$.get('http://www.jstest.com/03kuayu.php?fn=?', {}, function(e){
//e就是另外域的PHP返回的数据
}, 'jsonp');
/* 方法二 */
$.ajax({
type:'get',
data:{},
dataType:'jsonp',
url:'http://www.js.com/jsonp.php?fn=?',
success:function(e){
//处理返回的数据
}
});
/* 方法三:专属jsonp */
$.getJSON(
'http://www.js.com/jsonp.php?callback=?',
function(e){
//e接受返回的数据
}
);
使用方法三,实现 jsonp 跨域请求
修改JavaScript代码:
$(function () {
$('btn').click(function () {
var url = "http://www.jstest.com/03kuayu.php?callback=?";
$.getJSON(url, function (res) {
console.log(res);
})
})
})
PHP
<?php
//echo "alert(123)";
//可以在php中echo js代码
//echo "fn()"; //告诉浏览器执行函数fn
$arr = [
['id'=>1,'name'=>'yaodao'],
['id'=>2,'name'=>'jack']
];
/* 响应数据,告诉浏览器调用函数输出数据 */
$res = json_encode($arr);
/* 多一步,获取地址栏的参数 */
$fn = $_GET['callback'];
echo "$fn($res)";
//在此调用函数fn,所以JavaScript中必须准备声明fn函数来接收数据
结果:
三、插件的编写
1. $.fn.extend();
使用此种方法需要传递对象形式的参数,对象中的每一个成员都是一个插件。
实例:
HTML
<!-- 测试对象 -->
<div style="color:blue">hello</div>
<p>123</p>
JavaScript
$(function(){
$.fn.extend({
red:function(){
$(this).css('color','red').css('background-color','red');
},
yellow:function(){
$(this).css('color','yellow').css('background-color','yellow');
},
//...自定义插件...
});
//测试
$('div').red();
$('p').yellow();
//注意:可以链式操作
})
效果:
2.$fn.xxx = function(){}
这种语法,只能够定义一个插件。
实例:
HTML
<!-- 测试对象 -->
<div style="color:blue">hello</div>
<p>123</p>
JavaScript
$(function(){
$.fn.newCss = function(color){
//$(this)表示调用插件的对象
$(this).css('color',color.x).css('background-color',color.y)
return $(this);//如果不return,无法链式操作
};
$('div').newCss({x:'white',y:'red'}).wrap($('<div></div>'));
})
效果:
注意:wrap($('<div></div>'))
包裹标签对象
3. 自定义插件(插件的应用)
(1)创建目录结构
将box.js、jquery-3.3.1.js引入到html中。
(2)HTML+CSS
HTML
<body style="width:2000px; height:2000px;">
<div id="left">
<div class="title">这是标题部分 <span>×</span></div>
<div class="content">这是内容区</div>
</div>
<div id="center">
<div class="title">这是标题部分 <span>×</span></div>
<div class="content">这是内容区</div>
</div>
<div id="right">
<div class="title">这是标题部分 <span>×</span></div>
<div class="content">这是内容区</div>
</div>
</body>
CSS
*{
padding:0;
margin:0;
border:0 none;
}
#left,#center,#right{
border:solid 1px black;
width:200px;
height:120px;
position: absolute;
display: none;
}
.title{
background-color: #92b8b1;
height:24px;
line-height: 24px;
padding:5px;
border-bottom: solid 1px black;
}
.content{
padding:5px;
}
.title span{
float: right;
cursor: pointer;
}
(3)调用插件
JavaScript
$(function () {
//自己的JS,调用插件,显示窗口
$('#left').box({zuo:'left', shang:'center'});
$('#center').box({zuo:'center', shang:'center'},'fadeOut');
$('#right').box({zuo:'right', shang:'bottom'},'slide');
});
(4)完成各个窗口的显示
box.js
$.fn.box = function (position) {
//参数样式position = {zuo:'left',shang:'center'}
var box = $(this);
//获取传参位置
var zuo = position.zuo;
var shang = position.shang
//声明真实的left和top值
var trueLeft;
var trueTop;
//获取浏览器窗口的宽度与高度
var win = $(window);
var winWidth = win.width();
var winHeight = win.height();
//获取div的宽度、高度
var boxWidth = box.outerWidth();
var boxHeight = box.outerHeight();
//获取滚动条的距离
var scrollLeft = win.scrollLeft();
var scrollTop = win.scrollTop();
//以九宫格的位置显示
//可选的zuo值有:left center right
//可选的shang值有:top center bottom
if (zuo == 'left') {
trueLeft = 0 + scrollLeft + 'px';
} else if (zuo == 'center') {
trueLeft = (winWidth - boxWidth) / 2 + scrollLeft + 'px';
} else if (zuo == 'right') {
trueLeft = winWidth - boxWidth + scrollLeft + 'px';
}
if (shang == 'top') {
trueTop = 0 + scrollTop + 'px';
} else if (shang == 'center') {
trueTop = (winHeight - boxHeight) / 2 + scrollTop + 'px';
} else if (shang == 'bottom') {
trueTop = winHeight - boxHeight + scrollTop + 'px';
}
//console.log(trueLeft,trueTop);
box.css('left', trueLeft).css('top', trueTop).show();
}
得到的效果:
(5)当浏览器改变时或滚动条滚动时,保持div的位置不变
实现原理:对获取的计算参数进行函数封装,当浏览器改变时或滚动条滚动时,调用函数重新计算。
封装三个函数:
第一个:获取浏览器的宽高及滚动条的滚动距离(原因:当浏览器改变时或滚动条滚动时,数值会发生改变,所以要重新计算。)
第二个:计算真实的left和真实的top值。
第三个:窗口的显示
修改box.js:
$.fn.box = function (position) {
//参数样式position = {zuo:'left',shang:'center'}
var box = $(this);
//获取传参位置
var zuo = position.zuo;
var shang = position.shang
//声明真实的left和top值
var trueLeft;
var trueTop;
//获取div的宽度、高度
var boxWidth = box.outerWidth();
var boxHeight = box.outerHeight();
//获取浏览器窗口的宽度与高度
var win;
var winWidth;
var winHeight;
//获取滚动条的距离
var scrollLeft;
var scrollTop;
/* 封装获取信息函数 */
function getVal(){
//获取浏览器窗口的宽度与高度
win = $(window);
winWidth = win.width();
winHeight = win.height();
//获取滚动条的距离
scrollLeft = win.scrollLeft();
scrollTop = win.scrollTop();
}
/* 封装计算函数 */
function calculate(){
//以九宫格的位置显示
//可选的zuo值有:left center right
//可选的shang值有:top center bottom
if (zuo == 'left') {
trueLeft = 0 + scrollLeft + 'px';
} else if (zuo == 'center') {
trueLeft = (winWidth - boxWidth) / 2 + scrollLeft + 'px';
} else if (zuo == 'right') {
trueLeft = winWidth - boxWidth + scrollLeft + 'px';
}
if (shang == 'top') {
trueTop = 0 + scrollTop + 'px';
} else if (shang == 'center') {
trueTop = (winHeight - boxHeight) / 2 + scrollTop + 'px';
} else if (shang == 'bottom') {
trueTop = winHeight - boxHeight + scrollTop + 'px';
}
}
/* 封装显示窗口函数 */
function show(){
box.css('left', trueLeft).css('top', trueTop).show();
}
/* 初始化显示一次 */
getVal();
calculate();
show();
/* 绑定浏览器改变大小事件、滚动条滚动事件 */
win.scroll(function(){
/* 重新计算与显示 */
getVal();
calculate();
show();
});
win.resize(function(){
/* 重新计算与显示 */
getVal();
calculate();
show();
});
}
最终效果:
滚动滚动条
缩小浏览器窗口