前端点滴(JS核心)(三)----倾尽所有
一、优化三表联动
1. 将数据库修改成文件
省市县的数据,不会经常变动,基本上可以认为是不变的数据。对于这样的数据,最好不要存到数据库,用文件存放也是一样的,而且用文件存放还可以减轻数据库的压力。所以用文件把省市县的数据存储,然后去查文件。
文件关联:
文件下载(city):
链接: https://pan.baidu.com/s/19s13smuDcTeaDTAU0UqG7Q
提取码: 94md
复制这段内容后打开百度网盘手机App,操作更方便哦
2. 简化 PHP 代码 (控制层)
复制city文件夹到项目中:
查询省、市、县的时候都根据文件名去查找,并且约定浏览器请求的时候,要传递filename参数,参数的值就是文件名(实际上就是省市县连接的关系,上述文件关系)。
所以:
PHP(06city.php)
<?php
//1. 判断书否含有参数,没有就表示获取省份(文件名0),有就根据参数查找文件
$filename = isset($_GET['filename']) ? $_GET['filename'] : 0; //php4-5语法形式
//$filename = $_GET['filename']??0; //php7 语法形式
//2.根据参数进行文件查询
echo file_get_contents('city/$filename.json');
//从PHP 5开始,FILE_USE_INCLUDE_PATH可用于触发包含路径搜索。
3. 修改 JavaScript 代码
(1)加载省份
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState==4 && xhr.status==200){
//接收服务器返回的数据
var result = xhr.responseText;
var res = JSON.parse(result);
//console.log(res); //JS数组
var sheng = document.getElementById('sheng');
for(var i in res){
var option = document.createElement('option');
option.setAttribute('value', res[i].id);//参数就是id,根据id查找对应的文件(通过文件名)
option.innerText = res[i].cn_name;
sheng.appendChild(option);
}
}
};
xhr.open('get', '06city.php', true);
xhr.send();
(2)加载对应的市
/* 切换sheng时,获取其对应的id值,后通过对应的id值查询文件(通过文件名) */
document.getElementById('sheng').onchange = function () {
// 获取 id
var id = this.value;
xhr.onreadystatechange = function () {
if(xhr.readyState==4 && xhr.status==200){
//接收服务器返回的数据
var result = xhr.responseText;
var res = JSON.parse(result);
var shi = document.getElementById('shi');
//把市的option放到select中之前,先重置select里面的内容
shi.innerHTML = '<option value="0">--请选择市--</option>';
document.getElementById('xian').innerHTML = '<option value="0">--请选择县--</option>';
for(var i in res){
var option = document.createElement('option');
option.setAttribute('value', res[i].id);
option.innerText = res[i].cn_name;
shi.appendChild(option);
}
}
};
//传递参数,查询对应的文件名,从而找到文件
xhr.open('get', '06city.php?filename='+id, true);
xhr.send();
}
(3)加载对应的区、县
/* 切换shi时,获取其对应的id值,后通过对应的id值查询文件(通过文件名) */
document.getElementById('shi').onchange = function () {
// 获取 id
var id = this.value;
xhr.onreadystatechange = function () {
if(xhr.readyState==4 && xhr.status==200){
//接收服务器返回的数据
var result = xhr.responseText;
var res = JSON.parse(result);
var xian = document.getElementById('xian');
//把县的option放到select中之前,先重置select里面的内容
xian.innerHTML = '<option value="0">--请选择县--</option>';
for(var i in res){
var option = document.createElement('option');
option.setAttribute('value', res[i].id);
option.innerText = res[i].cn_name;
xian.appendChild(option);
}
}
};
xhr.open('get', '06city.php?filename='+id, true);
xhr.send();
}
4. 简化 JavaScript 代码(封装函数)
//请求函数
function get(url,fn){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4&&xhr.status == 200){
var result = xhr.responseText;
var res = JSON.parse(result);
fn(res);
}
}
xhr.open('get','url',true);
xhr.send();
}
//返回数据处理函数
function callback(res,ele){
for(var i in res){
var option = document.createElement('option');
option.setAttribute('value', res[i].id);
option.innerText = res[i].cn_name;
ele.appendChild(option);
}
}
//DOM操作节点函数
function $(id){
return document.getElementById(id)
}
/* 获取省份 */
/* 使用匿名会回调函数获取数据,后进行调用处理 */
get('06city.php',function(data){
chuli(data,$('sheng'));
})
/* 获取市 */
$('sheng').onchange = function(){
var id = this.value;
get('06city.php?filename='+id,function(data){
//重置市
$('shi').innerHTML = '<option value="0">--请选择市--</option>';
//重置县
$('xian').innerHTML = '<option value="0">--请选择县--</option>';
//数据处理
chuli(data,$('shi'));
})
}
/* 获取区 */
$('shi').onchange = function(){
var id = this.value;
get('06city.php?filename='+id,function(data){
//重置县
$('xian').innerHTML = '<option value="0">--请选择县--</option>';
//数据处理
chuli(data,$('xian'));
})
}
写的$、get函数做什么项目都可以使用,可以将这两个函数写到一个js文件中。
所以根据上述的函数封装就引出了所谓的 jQuery 库,实际上就是 JavaScript 的函数封装。
二、XML
1. 什么是 XML
XML(eXtensible Markup Language):可扩展标记语言
用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。
xml也是一种标记(标签)语言,它的侧重点是描述数据,而相似的HTML主要用于展示数据。
标签特点:
- XML标签可以自己定义(带有语义化)
- HTML标签固定
意义:
- XML用于存储数据,用浏览器打开没有特殊效果,就是一个树状结构
- HTML用于展示数据,每个标签都有各自的样式。
2. XML 的媒介作用
在web开发领域,XML的作用主要是:
- 存储数据,充当小型数据库;
- 当做配置文件;
- 当做两种编程语言交互数据的中间媒介,类似JSON。
3. XML 实例
XML也是标签语言,标签可以自定义,但XML的语法更加严格。在编写XML文件的时候,要注意下面几点:
- 文档声明:
<?xml version='1.0' encoding='utf-8'?>
,必须存在,写在开头。 - 标签必须闭合,即使是单标记标签,如
<age></age >
- 属性必须加引号
- 区分大小写
- 文档有且只有一个根标签
/* 07XMLtest.xml */
<?xml version = '1.0' encoding = 'utf-8'?>
<student> <!- 一个根标签 ->
<stu>
<name>yaodao</name>
<age>25</age>
<sex>男</sex>
</stu>
<stu>
<name>jack</name>
<age>20</age>
<sex>男</sex>
</stu>
</student>
4. PHP 返回 XML 格式的数据
JavaScript
<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
var res = xhr.responseXML;
console.log(res);
}
xhr.open('get','08phpandXML.php',true);
xhr.send();
</script>
PHP(08phpandXML.php)
<?php
//必须指定header,告诉浏览器,返回的内容是xml格式
header('content-type:text/xml');
//读取xml文件,然后返回
echo file_get_contents('07XMLtest.xml');
返回结果:
5. 浏览器处理 XML 格式数据
返回的结果可以当做document对象来使用。也就是说,可以调用getEle….系列方法,DOM中曾经学习过的大部分方法都可以使用。简而言之,就是可以把返回的结果当做一个HTML文档来处理。
<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
var res = xhr.responseXML;
console.log(res);
var stus = res.getElementsByTagName('stu');
document.write('<table border="1" width="300">')
for(var i in stus){
document.write('<tr>');
document.write('<td>'+stus[i].children[0].innerHTML+'</td>');
document.write('<td>'+stus[i].children[1].innerHTML+'</td>');
document.write('</tr>');
}
document.write('</table>');
}
xhr.open('get','08phpandXML.php',true);
xhr.send();
</script>
三、FromData 对象
1. 什么是 FromData 对象
FormData:字母意思就是表单数据,这是h5中新增的一个内置对象(构造器),它可以获取任何类型的表单项的值,比如text/radio/checkbox/file/textarea,适用于获取大量的表单项的值。常用于发送Ajax请求。
优点:简单的代码,就能将表单中所有类型的数据都收集到,包括文件域的内容,非常方便。
缺点:因为是h5新增,所以IE9+才支持。
2. 使用 FromData 对象搜集表当数据并发送异步请求
注意点:
- 必须使用post请求,并使用FormData的时候,不用设置请求头
xhr.setRequestHeader()
; - 有文件域,但是不用设置
enctype
。 - 获取表单的内容使用
$_POST
,获取文件域的内容使用$_FILES
- 收集表单项的值是根据表单项的name值获取的
HTML
<form name="myform">
用户名:<input type="text" name="username"><br>
密 码:<input type="password" name="pwd"><br>
性 别:
<input type="radio" name="sex" value="男" checked>男
<input type="radio" name="sex" value="女" >女<br>
爱 好:
<input type="checkbox" name="hobby[]" value="吃饭">吃饭
<input type="checkbox" name="hobby[]" value="睡觉">睡觉
<input type="checkbox" name="hobby[]" value="看书">看书<br>
图 片:<input type="file" name="pic"><br>
地 址:
<select name="address">
<option value="北京">北京</option>
<option value="广东">广东</option>
<option value="天津">天津</option>
</select>
<br>
简 介:<textarea name="introduce" cols="45" rows="3"></textarea><br>
<input type="button" value="提交" id="btn">
</form>
PHP(09Form_Data.php)
<?php
// 将表单数据(文本数据)保存在post.txt文件中
file_put_contents('post.txt', print_r($_POST,true)); //返回php数据格式数据到文件中
// 将上传文件信息保存在file.txt文件中
file_put_contents('file.txt', print_r($_FILES,true));
JavaScript
<script>
//找button按钮,绑定单击事件
document.getElementById('btn').onclick = function () {
/***** 收集表单数据 *****/
var form = document.myform; //0级DOM
var fd = new FormData(form); //获取表单数据
/***** 发送Ajax请求 *****/
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
};
xhr.open('post', '09Form_Data.php');
xhr.send(fd);
};
</script>
结果:
3. 使用 FromData 完成异步上传
在使用FromData完成异步上传后产生了两个text(表单信息、上传文件信息)信息文件,但是缺少了实例文件(上传的文件)比如:图片;文件;视频…
所以进一步创建目录保存上传的文件
修改PHP(09Form_Data.php)
/* 创建文件夹保存上传文件 */
<?php
/* 1、搜集上传文件信息以及表单信息 */
file_put_contents('post.txt', print_r($_POST,true));
file_put_contents('file.txt', print_r($_FILES,true));
/* 2、自动创建目录保存上传文件 */
$dir = './uploads/'.date('Y/m/');
if(!file_exists($dir)){
mkdir($dir,0777,true); //0777表示最高权限
}
/* 3、制定不重复的文件名 */
//文件名
$filename = uniqid();
//后缀名
$png = strrchr($_FILES['pic']['name'], '.'); //获取上传文件信息中的文件名,后从‘.’开始截取到最后
//组合、放入、移动语法:move_uploaded_file(旧地址,新地址)
move_uploaded_file($_FILES['pic']['tmp_name'],$dir.$filename.$png)
效果:
扩展:
0777概念:
权限(二进制) | r(可读) | w(可写) | x(可执行) | 十进制 |
---|---|---|---|---|
特殊权限位 | 0 | 0 | 0 | 0 |
owner(拥有者位) | 1 | 1 | 1 | 7 |
group(同组用户位) | 1 | 1 | 1 | 7 |
other(其余用户位) | 1 | 1 | 1 | 7 |
表示拥有者、同组用户、其余用户都具有读、写、执行的权限。
特殊权限位说明:
- setuid位, 如果该位为1, 则表示设置setuid
- setgid位, 如果该位为1, 则表示设置setgid
- sticky位, 如果该位为1, 则表示设置sticky
setuid: 设置使文件在执行阶段具有文件所有者的权限. 典型的文件是 /usr/bin/passwd。如果一般用户执行该文件, 则在执行过程中, 该文件可以获得root权限, 从而可以更改用户的密码。
setgid: 该权限只对目录有效. 目录被设置该位后, 任何用户在此目录下创建的文件都具有和该目录所属的组相同的组。
sticky bit: 该位可以理解为防删除位. 一个文件是否可以被某用户删除, 主要取决于该文件所属的组是否对该用户具有写权限。
如果没有写权限, 则这个目录下的所有文件都不能被删除, 同时也不能添加新的文件。如果希望用户能够添加文件但同时不能删除文件,则可以对文件使用sticky bit位。设置该位后, 就算用户对目录具有写权限, 也不能删除该文件。
4. 异步上传实现进度条效果
(1)准备
因为是本地,上传速度非常快,所以上传一个小文件看不出进度条。所以上传大文件。上传大文件就需要修改php.ini,主要修改三个max。
使用 wampserver
1)点击wampserver图标
2)选中PHP中的php.ini
3)对以下参数进行修改
(2)Ajax 对象中的 upload 属性
代码:
打印结果:
继续打印xhr.upload:
添加onprogress事件,并打印事件对象:
document.getElementById('btn').onclick = function () {
/***** 收集表单数据 *****/
var form = document.myform; //0级DOM
var fd = new FormData(form); //获取表单数据
/***** 发送Ajax请求 *****/
var xhr = new XMLHttpRequest();
// console.log(xhr);
// console.log(xhr.upload);
/* 绑定事件,打印事件对象 */
xhr.upload.onprogress = function(el){
console.log(el);
}
xhr.onreadystatechange = function () {
};
xhr.open('post', '09Form_Data.php');
xhr.send(fd);
};
打印结果:
(3)制作进度条
使用 H5 progress 标签,制作进度条
修改上述代码:
document.getElementById('btn').onclick = function () {
/***** 收集表单数据 *****/
var form = document.myform; //0级DOM
var fd = new FormData(form); //获取表单数据
/***** 发送Ajax请求 *****/
var xhr = new XMLHttpRequest();
// console.log(xhr);
// console.log(xhr.upload);
var prog = document.getElementsByTagName('progress')[0];
/* 绑定进程事件 */
xhr.upload.onprogress = function(el){
prog.setAttribute('value',el.loaded);
prog.setAttribute('max',el.total);
prog.style.display = 'block';
}
xhr.onreadystatechange = function () {
};
xhr.open('post', '09Form_Data.php');
xhr.send(fd);
};
结果:
四、跨域请求
1.前期准备
配置 wampserver 多域名(站点)
1)启动wampserver(等待绿标)–> 点击绿标找到Apache --> 使用记事本打开其中的 httpd-vhosts.conf 文件。
httpd-vhosts.conf 文件配置用于多个域名,注意: 原域名尽量不要动。
2)使用记事本打开Apache中的 httpd.conf 文件
由于httpd-vhosts.conf是扩展文件,要确保httpd-vhosts.conf的配置是被引用,有些版本默认是注释的。ctrl+f搜索hosts,解其搜索结果下的 #
3)同样是这个文件,ctrl+f搜索controls,修改搜索结果下的内容。
4)使用记事本打开C:\Windows\System32\drivers\etc路径下的hosts文件,添加站点。注意: 站点要和1步骤中的自定义域名相同。
5)将所有的记事本保存,重启wampserver,进行测试。
在各自存放文件的路径中新建文件
6)打开浏览器在地址栏中输入
2. 同源政策
1995年,同源政策由 Netscape(网景) 公司引入浏览器。目前,所有浏览器都实行这个政策。
最初,它的含义是指,A 网页设置的 Cookie,B 网页不能打开,除非这两个网页同源。所谓同源指的是三个相同。
- 协议相同(http https)
- 域名相同
- 端口相同(默认80端口)
随着互联网的发展,同源政策越来越严格。目前,如果非同源,共有三种行为受到限制。
- Cookie无法读取。
- DOM 无法获得。
- AJAX 请求无效(可以发送,但浏览器会拒绝接受响应)。
3. 什么是跨域请求
其实,了解了什么是同源政策,就知道什么是跨域请求了。
在发送Ajax请求的时候,请求的地址只要违反了同源政策,那么就属于跨域请求。
浏览器返回结果:
4. 实现跨域请求
(1)代理方式实现跨域请求
发送Ajax请求的时候,请求本网站的php文件,让本网站的php文件去请求另外网站的内容。
www.ajaxtest.com:01kuayu.html
www.ajaxtest.com:01kuayu.php
www.jstest.com:01kuayu.php
结果:
(2)cors方式实现请求(设置访问权限)
www.ajaxtest.com:02kuayu.html
www.jstest.com:02kuayu.php
结果:
(3) 使用JSONP技术实现跨域请求
Jsonp(JSON with Padding) 是 json 的一种"使用模式",通俗的讲,jsonp可以通过html标签中的src属性可以访问另外域的内容,可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
参考:https://www.runoob.com/json/json-jsonp.html