一、通信过程
客户端请求、服务器处理和响应
· 在网页中请求服务器上的资源
XMLHttpRequest对象:
var xhrObj = new XMLHttpRequest()
二、Ajax
· 介绍
Ajax全称异步的JS和XML(Asynchronous JavaScript And XML)
XML extensible markup language
· 客户端请求数据的方法
由于JQuery中封装了XMLHttpRequest对象,因此我们可以通过以下方法向服务器发起请求
get
向服务器获取资源
1. 格式:
$.get(url,[data],[callback])
2. 实例
// 1、发起不带参数的get请求:获取所有数据
$('.btn1').on('click', function () {
$.get('http://www.liulongbin.top:3006/api/getbooks', function (res) {
console.log(res);
// 返回的res对象中包含status、msg和data(data是一个数组,数组中元素都是一个对象)
});
});
// 2、发起带参数的get请求:获取id等于1的数据
$('.btn2').on('click', function () {
$.get('http://www.liulongbin.top:3006/api/getbooks',
{ id: 1 },
function (res) {
console.log(res);
});
});
post
向服务器提交数据
1. 格式
$.post(url,[data],[callback])
2. 实例
// 3、发起post请求
$('.btn3').on('click', function () {
$.post('http://www.liulongbin.top:3006/api/addbook', {
bookname: '红楼梦',
author: '忘记了',
publisher: '天津图书出版社'
}, function (res) {
console.log(res);
// res对象中包含status和msg
});
});
ajax
可以通过ajax发起get、post等请求
1. 格式
$.ajax({
type:'', // 请求的方式,例如get或post
url:'', // 请求的地址
data:'', // 这次请求要携带的数据
success: function(res){} // 请求成功的回调函数
})
2. 实例
// 4、使用$.ajax()发起get请求
$('.btn4').on('click', function () {
$.ajax({
type: 'GET',
url: 'http://www.liulongbin.top:3006/api/getbooks',
data: { id: 1 },
success: function (res) {
console.log(res);
// res对象包含status、msg和data
}
});
});
// 5、使用$.ajax()发起post请求
$('.btn5').on('click', function () {
$.ajax({
type: 'post',
url: 'http://www.liulongbin.top:3006/api/addbook',
data: {
bookname: '上下五千年',
author: '不知道',
publisher: '北京图书出版社'
},
success: function (res) {
console.log(res);
// res对象包含status和msg
}
});
});
三、接口
· 介绍
客户端请求的url地址就是数据接口
·接口文档
接口文档说明,是调用接口的依据,包含了接口url、参数、输出内容的说明
- 接口名称:如登录接口、获取图书列表接口
- 接口url:接口调用地址
- 接口方式:如get、post
- 参数格式:接口需要传递的参数,包含参数名称、参数类型、是否必选、参数说明
- 响应格式:接口返回值的详述描述,包含数据名称、数据类型、说明
- 返回示例:通过对象形式,例举服务器返回数据的结构
四、form表单
· 简介
在浏览器的表单中填写数据,通过form表单提交操作,把客户端填写的数据提交给服务器
· 组成
- 表单标签(form)
- 表单域(包含文本框、密码框、隐藏域、多行文本框、复选框、单选框、下拉框、文件上传框)
- 表单按钮(submit类型按钮)
· form标签属性
-
action:url地址 规定向何处发送表单数据,未指定时默认值为当前页面url
-
method:get或post 规定以何种方式把表单数据提交到url
-
enctype:规定在表单发送之前是否对数据进行编码
1、application/x-www-form-urlencoded(默认值,再发送前编码所有字符) 2、multipart/form-data(不对字符编码,在上传文件时必须使用) 3、text/plain(空格转化为'+'加号,但不对特殊字符编码)
-
target:规定在何处打开action的url
1、_blank 新窗口中打开action url 2、_self 在本窗口打开url 3、_parent 在父窗口中打开 4、_top 在整个窗口中打开 5、framename 在指定窗口中打开
实例:html代码
<!-- 1、表单 -->
<form action="\login" id="form1" method="post" role="form" class="typepage" target="_blank">
<legend>LOGIN</legend>
<div class="form-group">
<label for="">name</label>
<input type="text" class="form-control" id="name" name="user_name" placeholder="Input name">
</div>
<div class="form-group">
<label for="">password</label>
<input type="text" class="form-control" id="password" name="password" placeholder="Input password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
· 表单的同步提交
介绍
通过submi按钮,触发表单提交操作,从而使页面跳转到action的url的行为
缺点
- 同步提交后,整个页面会跳转到action url,用户体验感差;
- 同步提交后,页面之前的状态和数据会丢失
解决
-
表单只负责采集数据,使用ajax将数据提交到服务器
-
阻止表单默认提交行为(跳转行为):event.preventDefault()
-
快速获取表单中的数据:$(selector).serialize()
// 1、表单提交方式一 $('#form1').submit(function (e) { e.preventDefault(); var data = $(this).serialize(); console.log(data); }) // 2、表单提交方式二 $("#form1").on('submit', function (e) { var data = $(this).serialize(); console.log(data); // 阻止表单跳转行为 e.preventDefault(); });
重置表单数据
reset()函数
功能:重置表单数据
属于JS中的方法,通过JQuery获取表单要转化成JS选择器才能调用该函数
1. JS获取表单选择器
var form = document.querySelector('#form')
form.reset()
2. JQuery获取表单数据
$('#form')[0].reset()
五、模板引擎
· 以前渲染页面
方法
单纯的借助$(selector).html(value)来渲染页面
var data = {
title: '<h3>用户信息<h3>',
name: 'yangzhiling',
age: 20,
isVIP: true,
regTime: new Date(),
hobby: ['吃饭', '睡觉', '烧屁屁']
}
$('#name1').html(data.name);
$('#title').html(data.title);
$('#age').html(data.age);
$('#isVIP').html(data.isVIP);
$('#regTime').html(data.regTime);
var rows = [];
$.each(data.hobby, function (index, item) {
rows.push('<li>' + item + '</li>');
});
$('.hobby').append(rows.join(''));
缺点
如果想要添加的页面内容发生改变,此时进行修改会很复杂和繁琐,因此引入模板引擎
· 介绍
本质上是一个art-template-web.js文件,里面含template函数,可以将数据对象插入自定义模板中,最终形成完整的html页面代码
· 优点
- 更容易维护
- 什么位置插入哪一个数据表达的很清楚
· 下载网址
https://aui.github.io/art-template/zh-cn/docs/installation.html
· 模板引擎使用步骤
1. 导入
<script src="js/art-template-web.js"></script>
// 导入template模板引擎之后,我们就可以通过
template('模板的id属性值','一个数据对象')
将自定义数据对象中每个数据插入到自定义模板中,形成完整的html页面代码
2. 定义数据对象
var data2 = {
name2: 'yangzhiling',
age2: 20,
flag: 0,
hobby2: ['吃饭', '睡觉', '探草', '拿五杀'],
regTime2: new Date()
}
3. 定义模板
1. 在script标签中定义模板
2. script标签默认type="text/javascript",即把script标签内容作为js解析
type="text/html"表示把script标签内容当做html解析
3. {{}}表示要填充数据的位置
<script type="text/html" id="tpl_user">
<h1>{{name2}}</h1>
<h1>{{age2}}</h1>
<div>
{{if flag===0}}
flag的值是0
{{else if flag===1}}
flag的值是1
{{/if}}
</div>
<div>
{{each hobby2}}
<li>{{$index}}{{$value}}</li>
{{/each}}
</div>
<h3>{{regTime2 | dateFormat}}</h3>
</script>
4. 调用template函数
var htmlstr = template('tpl_user', data2);
// template函数返回的是html代码字符串
5. 渲染页面
1. 在html代码定义一个容器
<div class="container typepage"></div>
2. 铜鼓$(selector).html(htmlstr)渲染页面
$('.container').html(htmlstr);
· 标准语法
介绍
{{ }}称为template的标准语法
基本形式
使用实例:
{{value}}
{{obj:key}}
{{pbj['key']}}
{{a?b:c}}
{{a||b}}
{{a+b}}
原文输出
{{@ value}}
// 一般在value的值中含html标签代码结构时使用原文输出
条件输出
1. 形式一
{{if value}}
满足条件时的插入内容
{{/if}}
2. 形式二
{{if value1}}
满足value1时的插入内容
{{else if value2}}
满足value2时的插入内容
{{/if}}
循环输出
1. 形式
{{each array}}
{{$index}}{{$value}}
{{/each}}
2. 实例
// 定义数据
var data = {
hobby: ['吃饭', '睡觉', '烧屁屁']
}
// 定义模板
<script type="text/html" id="tpl_user">
<div>
{{each hobby2}}
<li>{{$index}}{{$value}}</li>
{{/each}}
</div>
</script>
// 数据通过template函数插入到模板中
var htmlstr = template('tpl_user', data);
过滤器
本质是通过一个处理函数对一个值进行处理得到一个新的值,在讲这个新的值插入页面
1. 形式
// filterName表示处理函数名,value表示将要被filterName函数处理的值
{{value | filterName}}
// 定义过滤器
template.defaults.imports.filterName = function(value) { return 处理结果 }
2. 实例
// 定义数据
var data = {
regTime2: new Date()
}
// 定义模板
<script type="text/html" id="tpl_user">
<h3>{{regTime2 | dateFormat}}</h3>
</script>
// 定义过滤器
<script>
template.defaults.imports.dateFormat = function (date) {
var y = date.getFullYear();
var m = date.getMonth() + 1;
var d = date.getDate();
return y + '-' + m + '-' + d;
}
</script>
// 数据通过template函数插入到模板中
var htmlstr = template('tpl_user', data);
· 模板引擎的实现原理
template函数中封装了一系列子功能函数,可以将data数据对象中的数据和模板中的{{value…}}通过正则表达式进行匹配,进而达到将数据插入模板的功能实现
知识前提
exec()函数作用
将自定义正则表达式代表的内容范围和一个字符串中的字符进行匹配,如果有匹配内容,则返回一个数组对象(对象中包含匹配到的内容 ”0”、匹配到这个内容的索引值”index"和被匹配的内容"input"等),如果没有匹配内容,返回null
1. 格式
var result = pattern.exec(str)
// pattern表示正则表达式,str表示被pattern匹配的字符串
2. 实例
var str = 'hello';
var pattern = /o/;
var result = pattern.exec(str);
console.log(result);
// 输出结果为一个数组:['o', index: 4, input: 'hello', groups: undefined]
正则表达式
JavaScript中的RegExp对象:https://www.runoob.com/js/js-obj-regexp.html
-
regular expression
-
语法格式:/ ‘一个表达式’/
-
+表示前面的字符出现1次或多次
*表示前面的字符出现0次或1次或多次
?表示前面的字符出现0次或1次
\s 表示匹配所有空白字符
正则表达式中加( … )表示不仅匹配符合整个/…/中表达式规则的字符串1,还要匹配符合( … )中表达式规则的字符串2,然后将两个字符串放在一个数组中作为结果输出
字符串操作函数
replace( ‘字符串1’ , ‘字符串2’ ) 表示用字符串2替换字符串1
实现原理
通过pattern.exec(str)函数将str中{{value}}和value两个字符串提取出来,然后通过str.replace({{value}},value在数据对象中作为属性对应的值)将str中的{{value}}替换为value在数据对象中作为属性对应的值,即可将str转化成包含真实数据的html代码字符串
实例:
// 10、replace替换为真值
var data = { name: '张三', age: 20 };
var str = '<div>{{name}}今年{{ age }}岁了</div>';
// 正则表达式加(),相当于同时匹配符合/{{\s*[a-zA-Z]+\s*}}/和/[a-zA-Z]+/正则表达式 // 的字符串
var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
var patternResult = null;
// 如果patternResult为空,即str中已经没有能够与pattern相匹配的字符串时,停止while // 循环
while (patternResult = pattern.exec(str)) {
// 使用data对象中patternResult[1]属性对应的值替换patternResult[0]字符串
str = str.replace(patternResult[0], data[patternResult[1]]);
}
console.log(str);
实现简单模板引擎
1. 添加html容器
<div class="user_box typepage"></div>
2. 定义模板引擎
<script type="text/html" class="typepage" id="xtpl_user">
<div>姓名:{{name}}</div>
<div>年龄:{{age }}</div>
<div>性别:{{ gender }}</div>
<div>住址:{{ address}}</div>
</script>
<script>
// 3. 定义数据
var datax = {
name: '朱元璋',
age: '1000',
gender: '男',
address: '中国明朝'
}
// 4. 调用模板引擎
var strx = templatex('xtpl_user', datax);
// 5. 渲染html结构
$('.user_box').html(strx);
// 6. 封装template函数
function templatex(id, data) {
var strx = document.getElementById(id).innerHTML;
var patternx = /{{\s*([a-zA-Z]+)\s*}}/;
var patternResultx = null;
while (patternResultx = patternx.exec(strx)) {
strx = strx.replace(patternResultx[0], data[patternResultx[1]]);
}
return strx;
}
</script>
六、XMLHttpRequest对象
· 介绍
XMLHttpRequest是浏览器提供的JS对象,可以借助该对象请求服务器上的资源,JQuery中ajax就是通过XMLHttpRequest进一步封装出来的
· 使用XMLHttpRequest发起get请求
// 1、创建xhr对象;
var xhr = new XMLHttpRequest();
// 2、调用xhr.open()函数
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks?id=1');
// 3、调用xhr.send()函数
xhr.send();
// 4、监听xhr.onreadystatechange事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
}
xhr的readystate属性
表示ajax请求处于什么样的状态
0 unsent表示xhr对象已经创建,但没有调用send方法
1 opened表示open方法已被调用
2 headers_received表示send方法已被调用,响应头也已经接受
3 loading表示数据接收中,此时response属性中已经包含部分数据
4 done表示ajax请求已经完成,意味数据传输彻底完成或失败
· 使用XMLHttpRequest发起post请求
// 1、创建xhr对象
var xhr = new XMLHttpRequest();
// 2、调用xhr.open()函数
xhr.open('post', 'http://www.liulongbin.top:3006/api/addbook');
// 3、设置Content-Type属性(固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded' );
// 4、调用xhr.send()函数,同时指定要发送的数据
xhr.send('bookname=水浒传&author=施耐庵&publisher=上海图书出版社');
// 5、监听xhr.onreadystatechange()事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
}
· 查询字符串
在url地址后面以?开头的字符串
- 查询字符串以?开头,其中的参数以’参数=值’键值对形式,参数之间用&隔开
- get携带参数的本质:无论使用 . g e t ( ) 还 是 使 用 .get()还是使用 .get()还是使用.ajax()或直接使用xhr对象发起get请求,都是将参数直接以查询字符串的形式追加到url地址后面
· URL编码
原则
- 只允许出现字母、标点符号、数字
- 不允许出现中文字符,如果url中需要包含中文字符,则必须对中文字符进行编码(转义)
encodeURL()编码函数
浏览器会自动对url地址进行编码
实例:
var str = encodeURL('黑马') // 结果返回:%E9%BB%91%A9%AC%E7
decodeURI()解码函数
实例:
var str = decodeURI('%E9%BB%91%A9%AC%E7') // 结果返回:黑马
七、数据交换格式
· 介绍
数据交换格式就是客户端和服务器之间以什么格式来交换数据,前端领域主要有JSON和XML两种数据交换格式
· XML
简介
XML为可扩展标记语言( Extensible Markup Language )
XML和HTML的区别
- HTML语言通过标签描述网页内容,是页面内容的载体
- XML主要用来存储数据和传输数据,是数据的载体
XML的缺点
- 格式臃肿,和数据无关的代码太多,体积大,传输效率低
- 在javascript中解析XML比较麻烦
· JSON
简介
JSON全称JavaScript对象表示法( JavaScript Object Notation )
- JSON使用文本表示JavaScript对象或数组
- JSON本质为字符串
- JSON是一种轻量级的文本数据交换格式,类似XML,专门用于存储和传输数据,但JSON比XML更小、更快、更易解析;
- JSON已成为主流数据交换格式;
JSON的两种数据结构
对象和数组
对象
格式:
{ "key" : "value", "key" : "value", ...}
// 1. key和value必须是英文双引号括起来的字符串
// 2. value的数据类型可以是数字、字符串、布尔值、null、数组、对象 6种类型
数组
格式:
[ "java", "javascript", 30, true ]
// 数组中类型可以是数字、字符串、布尔值、null、数组、对象 6种类型
JSON语法原则
- 属性名必须使用双引号包裹
- 字符串类型的值必须使用双引号包裹
- JSON中不允许使用单引号表示字符串
- JSON中不能写注释
- JSON的最外层必须是对象和数组格式
- 不能使用undefined或函数作为JSON的值
本质
用字符串表示JavaScript对象或数组
1. js对象 var obj = {a:'hello',b:'world'}
2. JSON字符串 var json = '{"a":"hello", "b":"world"}'
JSON和JS对象的转化
-
反序列化——JSON字符串转化为JS对象:JSON.parse()函数
var obj = JSON.parse( '{"a":"hello","b":"world"}' ) // 结果:{ a : "hello", b : "world" }
-
序列化——JS对象转化为JSON字符串:JSON.stringify()函数
var jsonstr = JSON.stringify(obj) // 结果:{ "a" : "hello", "b" : "world" } // 该结果为字符串
实例:
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks')
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// xhr对象中的response和responseText都为JSON字符串格式,这里将其 // 转化为JS对象输出
var result = JSON.parse(xhr.responseText);
console.log(result);
}
}
八、封装自定义Ajax函数
· 步骤
-
通过自定义函数yangzhiling()发起get和post请求
yangzhiling( 参数 ) 中参数为method、url、data和success属性组成的对象
// 发起get请求 yangzhiling({ method: "get", url: "http://www.liullongbin.top:3006/api/getbooks", data: { id: 1 }, success: function(res){ console.log(res) } }) // 发起post请求 yangzhiling({ method: "post", url: "http://www.liullongbin.top:3006/api/addbook", data: { bookname: "我的一生", author: "我", publisher: "心脏出版社" }, success: function(res){ console.log(res) } })
-
自定义函数:resolveData()函数
功能:将客户端发来的data数据对象转化为以?开头的查询字符串
function resolveData(data){ var arr = [] for(var k in data){ var str = k + '=' + data[k] arr.push(str) } return '?' + arr.joim('&') }
-
封装yangzhiling( options )自定义函数
功能:客户端可以通过该函数发送method、url、data和success组成的options对象,并且服务器会处理数据并返回响应结果
function yangzhiling(options){ var xhr = new XMLHttpRequest() // 将options.data对象转化为查询字符串 var qs = resolveData(options.data) // 判断请求方式是get还是post // str.toUpperCase()表示将str字符串字符全部转化为大写字母 if (options.method.toUpperCase() === "GET"){ // 发起get请求 xhr.open(options.method, options.url + qs) xhr.send() // 这里先不定义success处理函数,判断完post之后再去定义 // 因为无论get还是post都要执行success } else if(options.method.toUpper() === "POST"){ // 发起post请求 xhr.open(options.method, options.url) // 设置请求头格式为文本类型,表单数据格式 xhr.setRequestHeader('Content-Type', 'application/x- www-form-urlencoded'); xhr.send(qs) } // 调用onreadystatechange监听请求是否成功 xhr.onreadystatechange = function(){ if(xhr.readyState === 4 && xhr.status === 200){ var ressult = JSON.parse(xhr.resposeText) options.success(result) } } }
九、XMLHttpRequest Level2新特性
· 旧版缺点
- 只支持文本数据的传输,无法来读取和上传文件
- 传输和接收数据时,没有进度信息,只能提示有没有完成
· Level2 新特性
timeout属性和ontimeout事件监听器
xhr.timeout属性设置请求时限,xhr.ontimeout事件监听请求时间是否超过请求时限并且执行超过时限的处理函数
var xhr = XMLHttpRequest()
xhr.timeout = 300
// 表示请求时限为0.3s,请求超过0.3s,就会触发ontimeout事件
xhr.ontimeout = function(){
console.log("请求超时了")
}
xhr.open("get","http://liulongbin.top:3006/api/getbooks")
xhr.send()
xhr.onreadystatechange = function(){
if(xhr.readychange === 4 && xhr.status === 200){
console.log(xhr.responseText)
}
}
FormData对象
关于FormData对象知识点
1. 创建Formdata对象实例
var form = document.getElementById('form')
var formData = new FormData(form)
2. 获取表单对象中的属性值
formData.get('key')
3. 设置表单中属性的值
formData.set('key', 'value')
4. 删除表单中属性的值
formData.delete('key')
5. 向表单中添加属性值
formData.append('key', 'value')
使用FormData对象获取表单数据
1. 格式
// 实例化FormData对象
var fd = new FormData(form)
...
// 将FormData对象发送给服务器
xhr.send(fd)
2. 实例
// 通过jquery获取表单选择器
$('#form').on('submit', function (e) {
e.preventDefault();
var fd = new FormData(this);
var xhr = new XMLHttpRequest();
xhr.open('post', 'http://liulongbin.top:3006/api/formdata');
xhr.send(fd);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
// 输出的fd为空
console.log(fd);
}
}
// 获取和输出完表单数据后,重置表单数据
$(this)[0].reset()
});
// 通过js的DOM获取表单选择器
var form = document.getElementById('form')
form.addEventListener('submit', function (e) {
e.preventDefault();
var fd = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.open('post', 'http://liulongbin.top:3006/api/formdata');
xhr.send(fd);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
console.log(fd);
}
}
$(this)[0].reset()
});
上传头像案例
xhr+进度条+FormData
上传头像案例:
1. 通过XMLHttpRequest发起post请求,使用FormData对象将文件数据上传到接口
2. 使用bootstrap中的进度条显示上传进度
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>上传头像</title>
<script src="../js/jquery v3.6.0.js"></script>
<link rel="stylesheet" href="../bootstrap/css/bootstrap.min.css">
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
position: relative;
margin: 30px auto;
width: 200px;
height: 200px;
border-radius: 50%;
}
#filechooser {
display: none;
}
.img_box1,
.img_box2 {
position: absolute;
width: 200px;
height: 200px;
background-color: orange;
border-radius: 50%;
text-align: center;
line-height: 200px;
font-size: 16px;
font-weight: 600;
color: rgb(172, 231, 11);
cursor: pointer;
user-select: none;
background-color: orange;
background-repeat: no-repeat;
background-size: 200px 200px;
background-image: url();
}
.img_box2 {
display: none;
}
.progress {
display: none;
position: absolute;
top: 90px;
left: 15px;
width: 200px;
height: 20px;
border-radius: 10px;
}
</style>
<body>
<div class="container">
<input type="file" name="" id="filechooser" title="">
<div class="img_box1" title="点击选择图片">选择头像</div>
<div class="img_box2" title="点击上传图片">上传头像</div>
<div class="progress">
<div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar" aria-valuenow="40"
aria-valuemin="0" aria-valuemax="100" style="width: 0%" id="persent">
<span class="sr-only">40% Complete (success)</span>
</div>
</div>
</div>
<script>
$('.img_box1').on('click', function () {
$('#filechooser').click()
})
$('#filechooser')[0].addEventListener('change',function (e) {
var files = $('#filechooser')[0].files
// 1. 拿到用户选择的文件
var file = e.target.files[0]
// 2. 将文件,转化为路径
var imgURL = URL.createObjectURL(file)
console.log(imgURL);
// 3. 将图片作为背景显示
if (files.length > 0) {
$(this)[0].style.display = 'none'
$('.img_box2')[0].style.display = 'block'
$('.img_box2')[0].style.backgroundImage = 'url(' + imgURL + ')'
}
})
$('.img_box2').click(upload_img)
function upload_img() {
var files = $('#filechooser')[0].files
if (files.length <= 0) {
return alert('请选择文件')
} else {
var formData = new FormData()
formData.append('avatar', files[0])
console.log(formData);
var xhr = new XMLHttpRequest()
// 使用进度条显示图片上传进度
$('.progress').css('display', 'block')
//通过监听xhr.upload.onprogress事件,获取文件上传进度
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
var persentage = Math.ceil((e.loaded / e.total) * 100)
$('#persent').attr('style', 'width:' + persentage + '%;').html(persentage + '%')
}
}
xhr.upload.onload = function () {
$('.progress').css('display', 'none')
}
xhr.open('post', 'http://liulongbin.top:3006/api/upload/avatar')
xhr.send(formData)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var data = JSON.parse(xhr.responseText)
if (data.status === 200) {
console.log(data);
$('.img_box1')[0].style.backgroundImage = 'url(http://liulongbin.top:3006' + data.url + ')'
$('.img_box2')[0].style.display = 'none'
$('.img_box1')[0].style.display = 'block'
alert('上传头像成功!')
} else {
console.log("图片上传失败!" + data.message);
}
}
}
}
}
</script>
</body>
</html>
ajax+加载图片+FormData
- ajaxStart(callback):一旦ajax请求开始,执行callbak
- ajaxStop(callback):一旦ajax请求结束,执行callback
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>上传头像</title>
<script src="../js/jquery v3.6.0.js"></script>
<link rel="stylesheet" href="../bootstrap/css/bootstrap.min.css">
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
position: relative;
margin: 30px auto;
width: 200px;
height: 200px;
border-radius: 50%;
}
#filechooser {
display: none;
}
.img_box1,
.img_box2 {
position: absolute;
width: 200px;
height: 200px;
background-color: orange;
border-radius: 50%;
text-align: center;
line-height: 200px;
font-size: 16px;
font-weight: 600;
color: rgb(172, 231, 11);
cursor: pointer;
user-select: none;
background-color: orange;
background-repeat: no-repeat;
background-size: 200px 200px;
background-image: url();
}
.img_box2 {
display: none;
}
#loading {
z-index: 99;
display: none;
position: absolute;
top: 80px;
left: 95px;
width: 40px;
height: 40px;
border-radius: 50%;
}
</style>
<body>
<div class="container">
<input type="file" name="" id="filechooser" title="">
<div class="img_box1" title="点击选择图片">选择头像</div>
<div class="img_box2" title="点击上传图片">上传头像</div>
<img src="../images/loading.gif" alt="" id="loading">
</div>
<script>
$('.img_box1').on('click', function () {
$('#filechooser').click()
})
$('#filechooser')[0].addEventListener('change', function (e) {
var files = $('#filechooser')[0].files
// 1. 拿到用户选择的文件
var file = e.target.files[0]
// 2. 将文件,转化为路径
var imgURL = URL.createObjectURL(file)
console.log(imgURL);
// 3. 将图片作为背景显示
if (files.length > 0) {
$(this)[0].style.display = 'none'
$('.img_box2')[0].style.display = 'block'
$('.img_box2')[0].style.backgroundImage = 'url(' + imgURL + ')'
}
})
// 使用动态图展示上传进度
$(document).ajaxStart(function () {
$('#loading').show()
})
$(document).ajaxStop(function () {
$('#loading').hide()
})
$('.img_box2').click(upload_img)
function upload_img() {
var files = $('#filechooser')[0].files
if (files.length <= 0) {
return alert('请选择文件')
} else {
var formData = new FormData()
formData.append('avatar', files[0])
$.ajax({
method: 'post',
url: 'http://liulongbin.top:3006/api/upload/avatar',
data: formData,
processData: false,
contentType: false,
success: function (res) {
$('.img_box1')[0].style.backgroundImage = 'url(http://liulongbin.top:3006' + res.url + ')'
$('.img_box2')[0].style.display = 'none'
$('.img_box1')[0].style.display = 'block'
console.log(res);
}
})
}
}
</script>
</body>
</html>
十、axios
· 引入axios在线js文件
官网地址: http://www.axios-js.com/zh-cn/docs/
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
· 优点
- 相较于XMLHttpRequest,axios更简单
- 相较于ajax,axios更轻量化,只专注于数据请求
· 形式
axios({
method:'请求类型',
url:'请求url地址',
data:{ /*post数据*/ },
params:{ /*get参数*/ }
}).then(callback)
· axios发起get请求
<button id="btn1">发起get请求</button>
document.querySelector('#btn1').addEventListener('click', function () {
var url = 'http://www.liulongbin.top:3006/api/get';
var paramsObj = { name: 'zs', age: 20 };
axios.get(url, { params: paramsObj }).then(function (res) {
console.log(res);
});
});
· axios发起post请求
<button id="btn2">发起post请求</button>
document.querySelector('#btn2').addEventListener('click', function () {
var url = 'http://www.liulongbin.top:3006/api/post';
var dataObj = { address: '背景', location: '顺义区' };
axios.post(url, { params: dataObj }).then(function (res) {
console.log(res.data);
});
});
· axios直接发起get请求
<button id="btn3">直接使用axios发起get请求</button>
document.querySelector('#btn3').addEventListener('click', function () {
var url = 'http://www.liulongbin.top:3006/api/get';
var paramsData = { name: '钢铁侠', age: 35 };
axios({
method: 'get',
url: url,
params: paramsData
}).then(function (res) {
console.log(res.data);
});
});
· axios直接发起post请求
<button id="btn4">直接使用axios发起post请求</button>
document.querySelector('#btn4').addEventListener('click', function () {
var url = 'http://www.liulongbin.top:3006/api/post';
axios({
method: 'post',
url: url,
data: {
name: '娃哈哈',
age: 18,
gender: '女'
}
}).then(function (res) {
console.log(res.data);
});
});
十一、防抖和节流
· 防抖
介绍
例如:事件a从触发到执行动作要10s,当a第一次被触发的10s内,又被触发一次,此时事件a会重第0s开始计算到执行动作的时间
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F3QiRR1S-1665487280434)(C:\Users\86137\AppData\Local\Temp\1653886518111.png)]
延时器:setTimeout()函数
我们通过延时器延迟某一事件从触发到执行动作的时间间隔,来达到防抖策略
作用
每一次触发事件,浏览器都会向服务器发起一次新的请求,通过定义延时器我们可以给事件从触发到执行动作之间加一段时间,减少客户端不必要的请求,减轻服务器压力
实例:淘宝防抖搜索框
- 主要实现功能:用户输入关键词,浏览器通过关键词向服务器发起请求,获取有关数据
- 解决问题:当用户清空关键词,有关数据列表容器也要清空并隐藏
- 优化:防抖和定义全局缓存对象,目的减少对服务器的请求,减缓服务器的压力
- 核心:只要这个事件被触发,就清除之前的延时器,重新加载一个新的延时器
<div class="container">
<!-- Logo -->
<img src=".././images/taobao_logo.png" alt="" class="logo" />
<div class="box">
<!-- tab 栏 -->
<div class="tabs">
<div class="tab-active">宝贝</div>
<div>店铺</div>
</div>
<!-- 搜索区域(搜索框和搜索按钮) -->
<div class="search-box">
<input id="ipt" type="text" class="ipt" placeholder="请输入要搜索的内容" /><button class="btnSea
搜索
</button>
</div>
<!-- 5.定义搜索建议列表,之后作为容器,通过html()将模板结构渲染到容器中 -->
<div id="suggest-list"></div>
</div>
</div>
<!-- 4.定义模板结构,用来插入相关项数据列表,同时定义模板之前先调用template的js包 -->
<script type="text/html" id="tpl-suggestList">
{{each result}}
<!-- $value[0]表示value是一个数组对象,这里只获取value中索引为0的值,$是each循环的循环项固定写法 -->
<div class="suggest-item">{{$value[0]}}</div>
{{/each}}
</script>
<script>
$(function () {
// 11.定义全局缓存对象
var cacheObj = {}
// 8.定义防抖函数
// 该函数功能:借助延时器setTimeout():当keyup事件触发,延迟一段时间再进行getSuggestList()的操作
function debounceSearch(keywords) {
var timer = setTimeout(function () {
getSuggestList(keywords)
}, 500)
}
// 当鼠标焦点在input中,每当按下键盘按键都会触发keyup事件
// 只有可以输入文字的标签才能触发keyup事件
// 1.给输入框绑定keyup事件,获取用户输入数据
$('#ipt').on('keyup', function () {
// 10.由于前一次keyup事件触发会加载延时器,第二次keyup事件触发需要向服务器发送新的数据请求,那么
// 因此,这里需要清除之前加载的延时器
clearTimeout(timer)
console.log('1');
var keywords = $(this).val().trim()
if (keywords.length <= 0) {
// 7.解决问题:如果清空搜索关键词,则html容器中的相关项列表也应该被清空并隐藏
return $('#suggest-list').empty().hide()
}
// 13.如果缓存对象中有新输入的keywords在其中作为属性,那么不必发起请求,直接调用renderSuggestLis
// 判断cacheObj中是否存储了新输入的keywords属性
if (cacheObj[keywords]) {
// 将该关键词在cacheObj中作为键对应的值传递给renderSuggestList()函数来渲染页面
return renderSuggestList(cacheObj[keywords])
}
// 3.如果数据不为空,则调用getSuggestList函数,根据keywords显示相关项的列表
// getSuggestList(keywords)
// 9.调用防抖搜索函数
debounceSearch(keywords)
})
function getSuggestList(keywords) {
// 2.根据用户输入的数据发起对服务器发起请求,获取与该数据有关的res.result数据列表
$.ajax({
method: 'get',
url: 'http://suggest.taobao.com/sug?q=' + keywords,
dataType: 'jsonp',
success: function (res) {
console.log(res);
}
})
}
// 6.html标签容器、template模板和res数据列表都有了,现在渲染页面
function renderSuggestList(res) {
if (res.result.length <= 0) {
// 6.1如果没有相关数据列表,则将html标签容器清空且隐藏
return $('#suggest-list').empty().hide()
}
// 6.2如果有相关数据,就借助template模板引擎函数渲染页面
// 疑问:这里使用res还是用res.result来渲染页面
var htmlstr = template("tpl-suggestList", res)
// 6.3通过$(selector).html(htmlstr)渲染页面并显示
$('#suggest-list').html(htmlstr).show()
// 12.当某一次请求数据列表和渲染页面都成功后,我们把这次数据进行缓存,给下一次请求调用
// 当对某一次输入的关键词的相关数据进行渲染页面之后,我们获取这个关键词
var keywords = $('#ipt').val().tirm()
// 把这个关键词作为属性值,把请求到的数据列表对象作为值存储到全局缓存对象中
cacheObj[keywords] = res
}
})
</script>
####· 节流
介绍
例如:事件a从触发到执行动作需要10s,在这10s中,无论事件a被触发多少次,动作依然会在10s时执行( 相当于这10s之中,只有第一次触发有效,其他触发无效 )
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tSGPAGQi-1665487280436)(C:\Users\86137\AppData\Local\Temp\1653886466790.png)]
应用场景
- 鼠标连续点击触发某一事件,但该事件在单位时间内只有第一次触发有效
- 懒加载技术
案例:节流+鼠标跟随效果
- 案例基本功能:实现图片跟随鼠标移动
- 使用节流作用:减少事件的触发,减缓浏览器压力
- 核心:一旦事件被触发,加载一个延时器;如果事件再次被触发,先判断之前的的延时器是否结束,如果没有结束,则这次触发作废;如果之前的延时器结束,则重新加载一个延时器
<style>
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
}
#angel {
position: absolute;
}
</style>
<!--
案例功能:实现图片跟随鼠标移动
使用节流作用:减少事件的触发,减缓浏览器压力
核心:1、一旦事件被触发,加载一个延时器
2、如果事件再次被触发,先判断之前的的延时器是否结束,如果没有结束,则这次触发作废
3、如果之前的延时器结束,则重新加载一个延时器
-->
<body>
<img src="../images/angel.gif" alt="" id="angel" />
<script>
$(function () {
var timer = null
$(document).on('mousemove', function (e) {
// 如果延时器为空,则加载新的延时器;如果不为空,则return,视这次触发无效
if (timer) { return }
timer = setTimeout(() => {
// $('#angel').css({ 'top': e.pageY + 'px', 'left': e.pageX + 'px' })
$('#angel').css('top', e.pageY + 'px').css('left', e.pageX)
console.log('ok');
// 这一次事件动作执行完毕后,清除延时器
timer = null
}, 20);
})
})
</script>
</body>
十二、JSONP
· 实现原理
通过script标签的src属性,请求跨域的数据接口,并通过函数调用的形式,接受跨域接口相应回来的数据
实例:
文件一:
<!-- 2、通过src属性调用外部js文件 -->
<script src="js/jsonpRealize.js?callback=abc"></script>
<script>
function abc(data) {
console.log('数据:');
console.log(data);
// 结果:数据:{ name: 'nihao', age: 90 }
}
</script>
文件二:jsonpRealize.js
abc({ name: 'nihao', age: 90 });
十三、HTTP协议
· 通信协议简介
客户端以什么样的格式发送请求数据,服务器以什么样的格式接收客户端发来的数据以及以什么样的形式处理和响应数据,这些格式就是客户端和服务器之间的通信协议
· HTTP简介
超文本传输协议( Hyper Text Transport Protocol )
· 请求消息( 请求报文 )
组成
请求行:请求方式、URL、HTTP协议版本(3个组成部分之间用空格隔开)
请求头:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
请求方法:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods
空行:分割请求头和请求体
请求体:含有向服务器提交的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1TANumWi-1665487280436)(C:\Users\86137\AppData\Local\Temp\1653892677760.png)]
· 响应状态码
网址:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
十五、Git
…
十六、Github远程仓库
…
ocument).on(‘mousemove’, function (e) {
// 如果延时器为空,则加载新的延时器;如果不为空,则return,视这次触发无效
if (timer) { return }
timer = setTimeout(() => {
// $(’#angel’).css({ ‘top’: e.pageY + ‘px’, ‘left’: e.pageX + ‘px’ })
$(’#angel’).css(‘top’, e.pageY + ‘px’).css(‘left’, e.pageX)
console.log(‘ok’);
// 这一次事件动作执行完毕后,清除延时器
timer = null
}, 20);
})
})
十二、JSONP
· 实现原理
通过script标签的src属性,请求跨域的数据接口,并通过函数调用的形式,接受跨域接口相应回来的数据
实例:
文件一:
<!-- 2、通过src属性调用外部js文件 -->
<script src="js/jsonpRealize.js?callback=abc"></script>
<script>
function abc(data) {
console.log('数据:');
console.log(data);
// 结果:数据:{ name: 'nihao', age: 90 }
}
</script>
文件二:jsonpRealize.js
abc({ name: 'nihao', age: 90 });
十三、HTTP协议
· 通信协议简介
客户端以什么样的格式发送请求数据,服务器以什么样的格式接收客户端发来的数据以及以什么样的形式处理和响应数据,这些格式就是客户端和服务器之间的通信协议
· HTTP简介
超文本传输协议( Hyper Text Transport Protocol )
· 请求消息( 请求报文 )
组成
请求行:请求方式、URL、HTTP协议版本(3个组成部分之间用空格隔开)
请求头:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
请求方法:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods
空行:分割请求头和请求体
请求体:含有向服务器提交的数据
[外链图片转存中…(img-1TANumWi-1665487280436)]
· 响应状态码
网址:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
十五、Git
…
十六、Github远程仓库
…