前端点滴(JS核心)(三)---- 使用 Ajax 实现多表联动(优化)、XML、FromData对象、跨域请求

一、优化三表联动

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(可执行)十进制
特殊权限位0000
owner(拥有者位)1117
group(同组用户位)1117
other(其余用户位)1117

表示拥有者、同组用户、其余用户都具有读、写、执行的权限。

特殊权限位说明:

  • 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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值