模板引擎
作用:使用模板引擎提供的模板语法,可以将数据和 HTML 拼接起来。
官方地址: aui.github.io/art-templat…
使用步骤
- 下载art-template模板引擎文件并在HTML页面中引入库文件
<script src="./js/template-web.js"></script>
- 准备 art-template 模板
<script id="tpl" type="text/html">
<div class="box"></div>
</script>
- 告诉模板引擎将哪一个模板和哪个数据进行拼接
var html = template('tpl', {username: 'zhangsan', age: '20'});
- 将拼接好的html字符串添加到页面中
document.getElementById('container').innerHTML = html;
- 通过模板语法告诉模板引擎,数据和html字符串要如何拼接
<script id="tpl" type="text/html">
<div class="box"> {{ username }} </div>
</script>
验证邮箱地址唯一性
- 获取文本框并为其添加离开焦点事件
- 离开焦点时,检测用户输入的邮箱地址是否符合规则
- 如果不符合规则,阻止程序向下执行并给出提示信息
- 向服务器端发送请求,检测邮箱地址是否被别人注册
- 根据服务器端返回值决定客户端显示何种提示信息
搜索框内容自动提示
- 获取搜索框并为其添加用户输入事件
- 获取用户输入的关键字
- 向服务器端发送请求并携带关键字作为请求参数
- 将响应数据显示在搜索框底部
省市区三级联动
- 通过接口获取省份信息
- 使用JavaScript获取到省市区下拉框元素
- 将服务器端返回的省份信息显示在下拉框中
- 为下拉框元素添加表单值改变事件(onchange)
- 当用户选择省份时,根据省份id获取城市信息
- 当用户选择城市时,根据城市id获取县城信息
FormData
FormData 对象的作用
-
模拟HTML表单,相当于将HTML表单映射成表单对象,自动将表单对象中的数据拼接成请求参数的格式。
-
异步上传二进制文件
-
准备HTML表单
<form id="form">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="button" />
</form>
- 将HTML表单转化为formData对象
var form = document.getElementById('form');
var formData = new FormData(form);
- 提交表单对象
xhr.send(formData);
FormData 对象的实例方法
对表单对象当中数据的操作,一般来说表单不会直接提交到服务器端,在用户点击提交按钮以后,客户端通常还要对表单的数据进行校验,这就要求我们能够获取表单数据当中的值,并能够对其校验或重新设置,这些操作都依赖FormData对象提供的一些方法
- 获取表单对象中属性的值
formData.get('key');
- 设置表单对象中属性的值
- 如果属性已存在会覆盖原有的值,如果属性不存在会创建这个属性
formData.set('key', 'value');
- 删除表单对象中属性的值
formData.delete('key');
- 向表单对象中追加属性值
formData.append('key', 'value');
注意: set方法与append 方法的区别是,在属性名已存在的情况下,set会覆盖已有键名的值,append会保留两个值。(服务器端不提前设置的情况下,同属性名默认接收最后一个值)
- 此处接收baima
FormData 二进制文件上传
<input type="file" id="file"/>
var file = document.getElementById('file')
// 当用户选择文件的时候
file.onchange = function () {
// 创建空表单对象
var formData = new FormData();
// 将用户选择的二进制文件追加到表单对象中
formData.append('attrName', this.files[0]);
// 配置ajax对象,请求方式必须为post
xhr.open('post', 'www.example.com');
xhr.send(formData);
}
FormData 文件上传进度展示
// 当用户选择文件的时候
file.onchange = function () {
// 文件上传过程中持续触发onprogress事件
xhr.upload.onprogress = function (ev) {
// 当前上传文件大小/文件总大小 再将结果转换为百分数
// 将结果赋值给进度条的宽度属性
bar.style.width = (ev.loaded / ev.total) * 100 + '%';
}
}
FormData 文件上传进度展示
// 当用户选择文件的时候
file.onchange = function () {
// 文件上传过程中持续触发onprogress事件
xhr.upload.onprogress = function (ev) {
// 当前上传文件大小/文件总大小 再将结果转换为百分数
// 将结果赋值给进度条的宽度属性
bar.style.width = (ev.loaded / ev.total) * 100 + '%';
}
}
FormData 文件上传图片即时预览
在我们将图片上传到服务器端以后,服务器端通常都会将图片地址做为响应数据传递到客户端,客户端可以从响应数据中获取图片地址,然后将图片再显示在页面中。
xhr.onload = function () {
var result = JSON.parse(xhr.responseText);
var img = document.createElement('img');
img.src = result.src;
img.onload = function () {
document.body.appendChild(this);
}
}
同源政策
Ajax 请求限制
Ajax只能向自己的服务器发送请求。比如现在有一个A网站,有一个B网站,A网站中的HTML文件只能向A网站服务器中发送Ajax请求,B网站的HTML文件只能向B网站发送Ajax请求,但是A网站是不能向B网站发送Ajax请求的,同理,B网站也不能向A网站发送Ajax请求。
- 如:请求天气信息
什么是同源
如果两个页面拥有相同的协议、域名和端口、那么这两个页面就属于同一个源,其中只要有一个不相同,就是不同源。
- www.example.com/dir/page.ht… http协议、
www.example.com域名、80端口 - www.example.com/dir2/other.… ——同源
- example.com/dir/other.h… ——不同源,域名不同
- v2.www.example.com/dir/other.h… ——不同源,域名不同
- www.example.com:81/dir/page.ht… ——不同源,端口不同
- www.example.com/dir/page.ht… ——不同源,协议不同
使用JSONP解决同源限制问题
jsonp是json with padding的缩写,它不属于Ajax请求,但它可以模拟Ajax请求。
- 将不同源的服务器端请求地址写在script标签的src属性中
<script src="http://localhost:3001"></script>
<script src=“https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
- 服务器端响应数据必须是一个函数的调用,真正要发送给客户端的数据需要作为函数调用的参数
const data = 'fn({name: "张三", age: "20"})';
res.send(data);
- 在客户端全局作用域下定义函数fn
function fn (data) { }
- 在 fn 函数内部对服务器端返回的数据进行处理
funciton fn (data) { console.log(data); }
跨域服务器代码
// 接收客户端传递过来得函数的名称
const fnName = req.query.callback;
// 将函数名称对应的函数调用代码返回给客户端
const data = JSON.stringify({name: "zhangsan"});
const result = fnName + `(${data})`;
setTimeout(() => {
res.send(result)
}, 1000);
- 使用jsonp()方法 在服务器端可以直接通过jsonp()方法实现跨域传参。
res.jsonp({name: 'lisi', age: 20});
JSONP 代码优化
- 客户端需要将函数名称传递到服务器端
- 将script请求的发送变成动态请求
- 封装jsonp函数,方便请求发送
- 优化服务器端代码
CORS 跨域资源共享
CORS: 全称为Cross-orifin resource sharing,即跨域资源共享,它允许浏览器向跨域服务器发送ajax请求,克服了Ajax只能同源使用的限制。
orgin: http://localhost:3000
Access-Control-Allow-Oringin: 'http://localhost:3000'
Access-Control-Allow-Oringin: '*'
访问非同源数据 服务器端解决方案
同源政策是浏览器给予Ajax技术的限制,服务器端是不存在同源政策限制。
服务器端开发人员可以直接访问非同源网站中的数据,所以做为客户端来讲,可以让自己的服务器端去获取非同源网站的数据,等到自己网站服务器端获取到数据之后再将数据响应到自己网站客户端,这样就绕过了浏览器的同源政策限制。
如:
用1号网站的客户端访问1号网站的服务器端,再由1号网站服务器端去获取2号网站中服务器端提供的数据,然后将获取到的数据响应到1号网站的客户端
got模块
npm安装
npm install got
引入got模块
const got = require('got');
使用got模块
(async () => {
try {
const response = await got('https://google.com');
console.log('statusCode:', response.statusCode);
console.log('body:', response.body);
} catch (error) {
console.log('error:', error);
}
})();
其中res.send(response.body);就是返回了对应非同源网站的数据,通过这种方法就可以实现绕过浏览器同源政策的限制。
cookie复习
网站应用分为服务器端和客户端两部分,由客户端发起请求,服务器端发起响应,两者在沟通时需要遵循HTTP协议中设定的规则。
HTTP规定了服务器端和客户端的沟通是无状态性的,服务器端不关心客户端是谁,只管对请求做出响应,响应一旦结束这次沟通也就结束了。
在现在的网站交互过程中需要服务器端识别客户端的身份,这时就需要用到cookie,cookie是用来实现服务器端与客户端身份识别的一种技术。
cookie相当于服务器端发送给客户端的身份证,当客户端第一次向服务器端发送请求的时候,服务器端检测当前客户端并没有对应的cookie,服务器端就会将cookie响应回客户端,这样客户端再次发送请求的时候就会携带cookie,自动发送给服务器端,服务器端就知道客户端是谁了。cookie建立了服务器端和客户端持久的联系。
withCredentials属性
在使用Ajax技术发送跨域请求时,默认情况不会在请求中携带cookie信息。
withCredentials:指定在涉及到跨域请求时,是否携带cookie信息,默认值为false
checkLogin.addEventListener('click', function () {
let xhr = new XMLHttpRequest();
// 对ajax对象进行配置
xhr.open('get', 'http://localhost:3001/checkLogin');
// 当发送跨域请求时,携带cookie信息
xhr.withCredentials = true;
// 发送ajax请求并传递请求参数
xhr.send();
// 监听服务器端给予的响应内容
xhr.addEventListener('load', function() {
console.log(xhr.responseText);
})
})
Access-Control-Allow-Credentials: true 允许客户端发送请求时携带cookie
app.use((req, res, next) => {
// 1. 允许哪些客户端访问我
// * 代表允许所有的客户端访问我
// header('响应头的属性名称','响应头属性名称对应的值')
// 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*,可以是具体的地址
res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
// 2. 允许客户端使用哪些请求访问我
res.header('Access-Control-Allow-Methods', 'get,post');
// 允许客户端发送跨域请求时携带cookie信息
res.header('Access-Control-Allow-Credentials', true);
next();
});