模板引擎
- 作用:使用模板引擎提供的模板语法,可以将数据和html拼接起来;
- https://aui.github.io/art-template/zh-cn/index.html
使用步骤
- 下载art-template模板引擎库文件并在html页面中引入库文件
<script src="js/template-web.js"></script>
- 准备art-template模板
<script id="tpl" type="text/html">
<div class="box">123</div>
</script>
- 告诉模板引擎将哪一个模板和哪个数据进行拼接
var html = template('tpl',{username:'andy',age:20});
- 将拼接好的html字符串添加到页面中
document.getElementById('container').innerHTML = html;
- 通过模板语法告诉模板引擎,数据和html字符串要如何拼接
<script id="tpl" type="text/html">
<div class="box">{{username}}</div>
</script>
案例:02-验证邮箱地址唯一性
案例:03-搜索框内容自动提示
案例:04-省市区三级联动
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 = doucument.getElementById('form');
var formData = new FormData(form);
- 提交表单对象(不能使用get方法);
xhr.send(formData);
案例:05-formdata对象的使用方法
app.js
//引入express框架
const express = require('express');
//路径处理模块
const path = require('path');
const formidable = require('formidable');
//创建web服务器
const app = express();
//静态资源访问服务功能
app.use(express.static(path.join(__dirname,'public')));
app.post('/formData',(req,res)=>{
//创建fromidable表单解析对象
const form = new formidable.IncomingForm();
//解析客户端传递过来的formdata对象
form.parse(req,(err,fields,files)=>{
// err:错误信息,fields:保存了表单当中的普通请求参数,files:和文件长传相关的信息
res.send(fields);
})
})
//监听端口
app.listen(3000);
//控制台提示输出
console.log('服务器启动成功');
html部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>05-formdata对象的使用方法</title>
</head>
<body>
<!-- 创建普通的html表单 -->
<form id="form">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="button" id="btn" value="提交"/>
</form>
<script>
//获取按钮
var btn = document.getElementById('btn');
//获取表单
var form = document.getElementById('form');
//为按钮添加点击事件
btn.onclick = function(){
//将普通表单转换为表单对象
var formData = new FormData(form);
//创建ajax对象
var xhr = new XMLHttpRequest();
//对ajax对象进行配置
xhr.open('post','http://localhost:3000/formData');
//发送ajax请求
xhr.send(formData);
//监听xhr对象下的onload事件
xhr.onload = function(){
if(xhr.status == 200){
console.log(xhr.responseText);
}
}
}
</script>
</body>
</html>
formData对象的实例方法
- 获取表单对象中的属性的值;
formData.get('key');
- 设置表单对象中属性的值
formData.set('key','value');
案例:06-formData对象的实例方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>06-formData对象的实例方法</title>
</head>
<body>
<!-- 创建普通的html表单 -->
<form id="form">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="button" id="btn" value="提交"/>
</form>
<script>
//获取按钮
var btn = document.getElementById('btn');
//获取表单
var form = document.getElementById('form');
//为按钮添加点击事件
btn.onclick = function(){
//将普通表单转换为表单对象
var formData = new FormData(form);
//获取表单对象属性的值
console.log(formData.get('username'));
//如果设置的表单属性存在,将覆盖这个表单属性
formData.set('username','itcast');
//如果设置的表单属性不存在,将会创建这个表单属性
formData.set('age',100);
//删除表单对象的属性
formData.delete('password');
//创建ajax对象
var xhr = new XMLHttpRequest();
//对ajax对象进行配置
xhr.open('post','http://localhost:3000/formData');
//发送ajax请求
xhr.send(formData);
//监听xhr对象下的onload事件
xhr.onload = function(){
if(xhr.status == 200){
console.log(xhr.responseText);
}
}
//创建空的表单对象
var f = new FormData();
//向表单对象中追加属性值
f.append('num','123');
console.log(f.get('num'));
//SET会覆盖原有的值,append会保留原有的值,再添加一个相同的属性
}
</script>
</body>
</html>
app.js对应06文件的部分
//对应06html
app.post('/formData',(req,res)=>{
//创建fromidable表单解析对象
const form = new formidable.IncomingForm();
//解析客户端传递过来的formdata对象
form.parse(req,(err,fields,files)=>{
console.log(fields);
// err:错误信息,fields:保存了表单当中的普通请求参数,files:和文件长传相关的信息
res.send(fields);
})
})
formData对象文件上传
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>07-formdata文件上传</title>
<style>
.progress{
width: 100px;
height: 20px;
}
.progress-bar{
height: 100%;
background-color: aquamarine;
}
</style>
</head>
<body>
<input type="file" name="" id="file">
<div class="progress" id="bar">
<div class="progress-bar" style="width: 60%">60%</div>
</div>
<script>
//获取文件选择器
var file = document.querySelector('#file');
//获取进度条元素
var bar = document.getElementById('bar');
//为文件选择控件添加onchange事件
//在用户选择文件后触发
file.onchange = function(){
//创建空表单对象
var formData = new FormData();
//将用户选择的二进制文件追加到表单对象中
formData.append('attrName',this.files[0]);
//创建ajax对象
var xhr = new XMLHttpRequest();
//配置ajax对象,请求方式必须为post
xhr.open('post','http://localhost:3000/upload');
//在文件上传的过程中持续触发
xhr.upload.onprogress = function(ev){
console.log(ev);
//ev.loaded 文件已经上传了多少
//ev.total 上传文件的总大小
var result = (ev.loaded / ev.total)*100+'%';
//设置进度条的宽度
bar.style.width = result;
//将百分比显示在进度条中
bar.innerHTML = result;
}
//发送ajax请求
xhr.send(formData);
//监听xhr对象下的onload事件
xhr.onload = function(){
//如果服务器返回的http状态码为200,说明请求成功
if(xhr.status == 200){
//将服务器返回的数据显示在控制台中
console.log(xhr.responseText);
}
}
}
</script>
</body>
</html>
app.js对应07的部分
// 对应07html
app.post('/upload',(req,res)=>{
//创建fromidable表单解析对象
const form = new formidable.IncomingForm();
//设置客户端上传文件的传输路径
form.uploadDir = path.join(__dirname,'public','upload');
//保留上传文件的后缀名字
form.keepExtensions = true;
//解析客户端传递过来的formdata对象
form.parse(req,(err,fields,files)=>{
// err:错误信息,fields:保存了表单当中的普通请求参数,files:和文件长传相关的信息
res.send('ok');
})
})
formData对象图片上传
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>07-formdata文件上传</title>
<style>
.progress{
width: 100px;
height: 20px;
}
.progress-bar{
height: 100%;
background-color: aquamarine;
}
</style>
</head>
<body>
<input type="file" name="" id="file">
<div class="progress" id="bar">
<div class="progress-bar" style="width: 60%">60%</div>
</div>
<div id="box"></div>
<script>
//获取文件选择器
var file = document.querySelector('#file');
//获取进度条元素
var bar = document.getElementById('#bar');
//
var box = document.getElementById('#box');
//为文件选择控件添加onchange事件
//在用户选择文件后触发
file.onchange = function(){
//创建空表单对象
var formData = new FormData();
//将用户选择的二进制文件追加到表单对象中
formData.append('attrName',this.files[0]);
//创建ajax对象
var xhr = new XMLHttpRequest();
//配置ajax对象,请求方式必须为post
xhr.open('post','http://localhost:3000/imgupload');
//在文件上传的过程中持续触发
xhr.upload.onprogress = function(ev){
console.log(ev);
//ev.loaded 文件已经上传了多少
//ev.total 上传文件的总大小
var result = (ev.loaded / ev.total)*100+'%';
//设置进度条的宽度
bar.style.width = result;
//将百分比显示在进度条中
bar.innerHTML = result;
}
//发送ajax请求
xhr.send(formData);
//监听xhr对象下的onload事件
xhr.onload = function(){
//如果服务器返回的http状态码为200,说明请求成功
if(xhr.status == 200){
//将服务器返回的数据显示在控制台中
console.log(xhr.responseText);
// 如果数据为数组
// 将服务器返回的数据显示在控制台中
var result = JSON.parse(xhr.responseText);
// 动态创建img表单
var img = document.createElement('img');
// 给图片标签设计src属性
img.src = result.path;
img.onload = function(){
box.appendChild(img);
}
}
}
}
</script>
</body>
</html>
app.js对应08的部分
//对应08实现
app.post('/imgupload',(req,res)=>{
//创建fromidable表单解析对象
const form = new formidable.IncomingForm();
//设置客户端上传文件的传输路径
form.uploadDir = path.join(__dirname,'public','upload');
//保留上传文件的后缀名字
form.keepExtensions = true;
//解析客户端传递过来的formdata对象
form.parse(req,(err,fields,files)=>{
// err:错误信息,fields:保存了表单当中的普通请求参数,files:和文件长传相关的信息
res.send({
//返回上传文件的地址
path:files.attrName.path.split('public')[1]
});
})
})
ajax请求限制
ajax只能向自己的服务器发送请求。
什么是同源
三个页面拥有相同的协议、域名和端口,那么这两个页面就属于同一个源,只要有一个不相同,就是不同源。
http://www.example.com/dir/page.html//端口默认80
http://www.example.com/dir2/other.html//同源
http://example.com/dir/other.html//不同源(域名不同)
http://www.example.com:82/dir/other.html//不同源(端口不同)
https://www.example.com/dir/page.html//不同源(协议不同)
同源政策
**目的:**为了保证用户信息的安全,防止恶意的网站窃取数据。最初的同源政策是指A网站在客户端设置的cookie,B网站是不能访问的。政策中有一规定:无法向非同源地址发送ajax请求,如果请求,浏览器就会报错。
使用JSONP解决同源限制的问题
JSONP:是json with padding的缩写,它不属于ajax请求,但是可以模拟ajax请求。
1、将不同源的服务器断请求地址卸载scrtpt标签的src属性中
<script src="www.example.com"></script>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
2、服务器响应数据必须是一个函数的调用,真正要发送给客户端的数据需要作为函数调用的函数
const data = 'fn{name:'zhangsan',age:20}';
res.send(data);
3、在客户端全局作用域下定义函数fn
function fn(data){}
4、在fn函数内部对服务器返回的数据进行处理
function fn(data){console.log(data)}