微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Ajax的学习整理

文章目录

来源博客:【Harryの心阁

Ajax运行原理

Ajax相当于浏览器发送请求与接受响应的代理人,以实现不影响用户浏览页面的情况下,局部更新页面数据,从而提高用户体验

实现步骤

  1. 创建Ajax对象 new XMLHttpRequest()
  2. 告诉Ajax请求地址以及请求方式 open
  3. 发送请求send方法
  4. 获取服务器端给予客户端的响应数据 onl oad 获取响应数据responseText
// 1. 创建ajax对象
var xhr = new XMLHttpRequest()
// 2. 告诉ajax对象发送的位置,和方式,第一个参数是请求方式,第二个请求地址
xhr.open('get', 'http://localhost:3000/first')
// 3. 发送请求
xhr.send()
// 4. 获取响应数据
xhr.onload = function(){
console.log(xhr.responseText);
}

响应的数据格式

  1. json对象作为响应数据的格式,请求返回的数据为json字符串
  2. 将json字符串转化为json对象
// 1. 创建ajax对象
var xhr = new XMLHttpRequest()
// 2. 告诉ajax对象发送的位置,和方式,第一个参数是请求方式,第二个请求地址
xhr.open('get', 'http://localhost:3000/responseData')
// 3. 发送请求
xhr.send()
// 4. 获取响应数据,接受完请求后onload事件自动响应
xhr.onload = function(){
// 返回的是字符串类型
// console.log(xhr.responseText);
// 将json字符串转换为json对象
let respnseText = JSON.parse(xhr.responseText)
console.log(respnseText);
console.log(typeof respnseText);
// 将转换的json对象中的信息获取,并且将数据信息渲染到页面中
let str = `<h2>${respnseText.name}</h2>`
document.body.innerHTML = str
}

请求参数传递

  1. get请求xx.open('get',url)
        let username =document.querySelector('#username')
        let email =document.querySelector('#email')
        let submit =document.querySelector('#submit')

        // 给按钮添加一个点击事件
        submit.onclick = function(){
            // 获取用户在表单中输入的值
            let emaildata = email.value
            let usernamedata = username.value
            // 对获取到数据进行字符串的拼接
            let str = `username=${usernamedata}&email=${emaildata}`
            // 创建一个ajax对象
            console.log(str);
            let xhr = new XMLHttpRequest()
            // 创建ajax对象的请求方式
            xhr.open('get',`http://localhost:3000/get?${str}`)
            xhr.send()
            xhr.onload = function(){
                console.log(xhr.responseText);
            }
        }
// res.send(req.query)
  1. get请求只能的请求头类型只能是application/x-www-form-urlencoded,并且在解析请求地址时通过 body-parser中的urlencoded()方法进行解析,get请求不能提交对象数据格式的

post请求方式

  1. 请求的方式为json时,如果要得到请求的json内容 需要使用 body-parser中的bodyPaser.json()方法
    // 1. 创建ajax对象
    var xhr = new XMLHttpRequest()
    // 2. 告诉ajax对象发送的位置,和方式,第一个参数是请求方式,第二个请求地址
    xhr.open('post', 'http://localhost:3000/json')
    xhr.setRequestHeader('Content-Type','application/json');
    
    // 3. 发送请求
    xhr.send(JSON.stringify({name:'list',age:50}))
    // 4. 获取响应数据,接受完请求后onload事件自动响应
    xhr.onload = function(){
        // 返回的是字符串类型
        console.log(xhr.responseText);
        // 将json字符串转换为json对象
    }

ajax状态码

  1. 获取服务器端的响应
  2. 0 请求未初始化
  3. 1 请求以及简历,但是还没有发送
  4. 2 请求已经发送
  5. 3 表示请求正在处理中,部分代码可以使用
  6. 4 响应已经完成
  7. xhr.readyState 获取Ajax状态码 onreadystatechange事件
  8. onload比以上事件的请求方式更为效率

ajax错误处理

  1. xhr.status获取http状态码 400
  var btn = document.getElementById('btn')
        // 当用户点击后发送错误请求
        btn.onclick=()=>{
            var xhr = new XMLHttpRequest()
            xhr.open('get','http://localhost:3000/error')
            // 对请求的http的状态码进行判断
            xhr.send();
            xhr.onload=()=>{
                console.log(xhr.status);
                if(xhr.status === 400){
                    alert(xhr.responseText)
                }
            }
        }
  1. 404错误状态码 输入错误的情况较多 ,检测请求地址是否有误
  2. 500错误代码时服务器端错误
  3. 断网时无法触发onload事件,可以执行onerror()事件

注意ajax状态码表示的是服务器的请求过程的状态,http状态码表示的是请求的结果

低版本的缓存问题

  1. 在请求地址上加一个参数,并且保证每次请求参数的值不同即可

同步异步

  1. 封装一个简单的异步函数get
  2. get请求需要拼接到请求地址的后方,post请求放在send的方法
function ajax (params){
    let xhr = new XMLHttpRequest();
    let options = ''
    params.data.forEach((v,i)=>{
        params += v + '=' + params.data[i] + '&'
    })
    params.substr(0,params.length-1)
    xhr.open(
        params.type,params.url
    )
    xhr.send()
    xhr.onload = ()=>{
        params.success(xhr.responseText)
    }
}
ajax({
    type:'get',
    url:'http://localhost:3000/first1',
    data:{
        name:'zs',
        age:20
    }
    success:(data)=>{
        console.log('这里是success函数'+data);
    }
})
  1. 封装get请求和post请求参数的时候
function ajax(params) {
    let xhr = new XMLHttpRequest();
    let options = ''
    for (let attr in params.data) {
        options += attr + '=' + params.data[attr] + '&'
    }
    options = options.substr(0, options.length - 1)
    // console.log(options)
    if (params.type === 'get') {
        params.url = params.url + '?' + options
    }
    xhr.open(params.type, params.url)
    if (params.type == 'post') {
        let contentType = params.header['Content-Type']
        xhr.setRequestHeader('Content-Type', contentType)
        if (contentType === 'application/json') {
            xhr.send(JSON.stringify(params.data))
        } else {
            xhr.send(options)
        }
    } else {
        xhr.send()
    }
    xhr.onload = () => {
        // 对http的状态码进行判断如果状态码为200则调用success函数,如果失败则调用error函数
        if (xhr.status == 200) {
            let responseHeader = xhr.getResponseHeader('Content-Type')
            let resText = xhr.responseText
            if (responseHeader.includes('application/json')) {
                resText = JSON.parse(resText)
            }
            params.success(resText, xhr)
        } else {
            params.error(resText, xhr)
        }
    }
}
ajax({
    type: 'get',
    url: 'http://localhost:3000/responseData',
    data: {
        name: 'sz',
        age: 20
    },
    header: {
        'Content-Type': 'application/json'
        // 'Content-Type':'application/x-www-form-urlencoded'
    },
    success: (data,xhr) => {
        console.log('这里是success函数');
        console.log(data);
        console.log(xhr);
    },
    error: (data) => {
        console.log('这里是error函数' + data);
    }
})
  1. 获取请求中的数据 getResponseHeader()方法页面加载完成后调用onload事件中 如果获取到的请求类型为application/json类型,将json字符串以json对象的方式输出,使用方法JSON.parse()
  2. object.assign() 如果目标对象和源对象有同名属性,或者多个源对象有同名属性,则后面的属性会覆盖前面的属性。如果该函数只有一个参数,当参数为对象时,直接返回该对象;当参数不是对象时,会先将参数转为对象然后返回。并且该方法浅拷贝
function ajax(params) {
    // 给ajax设定一个认值
    let defaults = {
        type: 'get',
        url: '',
        data: {},
        header: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        success: (data) => {

        },
        error: (data) => {

        }
    }
    // 使用object.assign()方法 将之间的对象覆盖
    Object.assign(defaults,params)
    let xhr = new XMLHttpRequest();
    let options = ''
    for (let attr in params.data) {
        options += attr + '=' + defaults.data[attr] + '&'
    }
    options = options.substr(0, defaults.length - 1)
    // console.log(options)
    if (defaults.type === 'get') {
        defaults.url = defaults.url + '?' + options
    }
    xhr.open(defaults.type, defaults.url)
    if (defaults.type == 'post') {
        let contentType = defaults.header['Content-Type']
        xhr.setRequestHeader('Content-Type', contentType)
        if (contentType === 'application/json') {
            xhr.send(JSON.stringify(defaults.data))
        } else {
            xhr.send(options)
        }
    } else {
        xhr.send()
    }
    xhr.onload = () => {
        // 对http的状态码进行判断如果状态码为200则调用success函数,如果失败则调用error函数
        if (xhr.status == 200) {
            let responseHeader = xhr.getResponseHeader('Content-Type')
            let resText = xhr.responseText
            if (responseHeader.includes('application/json')) {
                resText = JSON.parse(resText)
            }
            defaults.success(resText, xhr)
        } else {
            defaults.error(resText, xhr)
        }
    }
}
ajax({
    url: 'http://localhost:3000/responseData',
    data: {
        name: 'sz',
        age: 20
    },
    success: (data, xhr) => {
        console.log('这里是success函数');
        console.log(data);
        console.log(xhr);
    }
})

模板引擎

  1. 使用模板引擎 art-template 在客户端的使用步骤
<!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/art-template.js"></script>
</head>
<body>
    <div class="container"></div>
    <script type="text/html" id="idt">
        <h1>{{username}} {{age}}</h1>
    </script>
    <script type="text/javascript">
        let html = template('idt',{username:'zs',age:20})
        document.querySelector('.container').innerHTML = html
    </script>
</body>
</html>

验证邮箱

<!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/ajax.js"></script>
    <!-- <script src="/js/template.js"></script> -->
</head>

<body>
    <style>
        body {
            background: -webkit-linear-gradient(left, rgb(216, 236, 235), rgb(241, 229, 241));
        }

        .Box {
            margin: 200px auto;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }

        .email_login {
            border-radius: 10px;
            width: 400px;
            height: 30px;
            padding: 10px;
            /* outline-color: aliceblue; */
        }

        .email_login:hover {
            outline-color: bisque;
            border: none;
        }

        .message {
            background: rgb(221, 208, 208);
        }

        .success {
            background-color: rgb(82, 82, 173);
        }

        .error {
            background-color: rgb(226, 106, 106);
        }
    </style>
    <div class="Box">
        <input type="email" class="email_login" value="" placeholder="请在此输入您要初测的邮箱账号!!">
        <p class="message"></p>
    </div>
    <script type="text/javascript">
        // 获取元素
        let email = document.querySelector('.email_login')
        let message = document.querySelector('p')
        // 当输入框失去焦点时的事件
        email.onblur = function () {
            // console.log(e);
            // 获取用户输入的值,对用户输入的值判断
            let email_value = this.value
            // 正则判断输入的值
            let reg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
            if (!reg.test(email_value)) {
                message.innerHTML = '输入的邮箱规则格式有误,请重新输入!!!'
                message.className = 'message'
                return;
            }
            ajax({
                type: 'post',
                url: "http://localhost:3000/emailBox",
                data: {
                    email: email_value
                },
                success: function (response) {
                    if (response.message.includes('恭喜')) {
                        message.innerHTML = response.message
                        message.className = 'success'
                    } else {
                        message.innerHTML = response.message
                        message.className = 'error'
                    }
                },
                error: (res) => {
                    message.innerHTML = res.message
                    message.className = 'error'
                }
            });
        }

    </script>
</body>
</html>

{% folding green, 请求路由 %}

app.get('/emailBox',(req,res)=>{
    if(req.query.email == 'iui[email protected]'){
        res.send({message:'您好邮箱已注册,请您重新输入!!'})
    }else{
        res.send({message:'恭喜您注册的邮箱可用!!!!'})
    }
})
app.post('/emailBox',(req,res)=>{
    if(req.body.email == 'iui[email protected]'){
        res.send({message:'您好邮箱已注册,请您重新输入!!'})
    }else{
        res.send({message:'恭喜您注册的邮箱可用!!!!'})
    }
})

{% folding green, ajax封装 %}

function ajax(params) {
    // 给ajax设定一个认值
    let defaults = {
        type: 'get',
        url: '',
        data: {},
        header: {
            'Content-Type': 'application/json'
        },
        success: (data) => {},
        error: (data) => {}
    }
    // 使用object.assign()方法 将之间的对象覆盖
    Object.assign(defaults,params)
    let xhr = new XMLHttpRequest();
    let options = ''
    for (let attr in params.data) {
        options += attr + '=' + defaults.data[attr] + '&'
    }
    options = options.substr(0, defaults.length - 1)
    // console.log(options)
    if (defaults.type === 'get') {
        defaults.url = defaults.url + '?' + options
    }
    xhr.open(defaults.type, defaults.url)
    if (defaults.type == 'post') {
        let contentType = defaults.header['Content-Type']
        xhr.setRequestHeader('Content-Type', contentType)
        if (contentType === 'application/json') {
            xhr.send(JSON.stringify(defaults.data))
        } else {
            xhr.send(options)
        }
    } else {
        xhr.send()
    }
    xhr.onload = () => {
        // 对http的状态码进行判断如果状态码为200则调用success函数,如果失败则调用error函数
        if (xhr.status == 200) {
            let responseHeader = xhr.getResponseHeader('Content-Type')
            let resText = xhr.responseText
            if (responseHeader.includes('application/json')) {
                resText = JSON.parse(resText)
            }
            defaults.success(resText, xhr)
        } else {
            defaults.error(resText, xhr)
        }
    }
}

搜索内容自动提示

  1. 使用定时器的操作,延时对请求接口发送ajax请求,在每次请求之前将之前的定时器清除
  2. 设置防抖操作,对用户输入的值进行判断如果用户没有在手术框中输入内容,将提示信息 使用trim()函数,将文本框中的空格清除 阻止程序向下执行 return

三级联动(省市区)

  1. 接口地址:接口地址
  2. JSON.stringify() 方法可以将对象的数据存储在本地的内存中
<!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/ajax.js"></script>
    <script src="js/art-template.js"></script>
</head>
<style>
    body {
        background-color: #ccc;
    }

    .Box {
        margin: 100px auto;
        width: 500px;
        height: 300px;
        display: flex;
        justify-content: center;
        align-items: center;
    }
</style>

<body>
    <div class="Box">
        <div class="form_group">
            <select name="" id="province">
                <!-- <option value="">请选择省份</option> -->
            </select>
        </div>
        <div class="form_group">
            <select name="" id="city">
                <option value="">请选择城市</option>
            </select>
        </div>
        <div class="form_group">
            <select name="" id="area">
                <option value="">请选择县城</option>
            </select>
        </div>
    </div>
</body>
<script type="text/html" id="provinceTpl">
    <option value="">请选择省份</option>
    {{each provices_list}}
        <option value="{{$value.pindex}}">{{$value.provices_list}}</option>
    {{/each}}
</script>
<script type="text/html" id="cityTpl">
    <option value="">请选择城市</option>
    {{each city_lists}}
    <option value="">{{$value.citysName}}</option>
    {{/each}}
</script>
<script>
    // 封装一个函数
    let All_lists = []
    function getaddressData() {
        ajax({
            type: "get",
            url: "https://cdn.jsdelivr.net/gh/Rr210/image@master/hexo/4/province1.json",
            success: function (response) {
                console.log(response);
                All_lists = response.provinces
                localStorage.setItem('address_data', JSON.stringify(response.provinces))
            }
        });
    }
    let province = document.querySelector('#province')
    let city = document.querySelector('#city')
    let addressData = localStorage.getItem('address_data')
    if (!addressData) {
        this.getaddressData()
    } else {
        All_lists = JSON.parse(addressData)
        let provices_list = All_lists.map((v,i) => {
            let arr = {provices_list:v.provinceName,pindex:i}
            return arr
        })
        // console.log(provices_list);
        let html = template('provinceTpl',{provices_list})
        province.innerHTML = html
    }
    // 给省份选择框添加一个改变事件监听 select的变化
    province.onchange = function(e){
        let id = this.value
        let city_lists = JSON.parse(addressData)[Number(id)].citys
        // console.log(city_lists);
        let html1 = template('cityTpl',{city_lists})
        city.innerHTML = html1
    }
</script>

</html>

FormData对象的作用

  1. 模拟HTML表单
  2. 异步上传二进制文件
  3. 本身是一个构造函数
  4. 使用formidable模块来解析FormData对象
  5. formData.get(‘属性名’),formData.set(‘属性名’,‘属性值’),formData.delete(‘key’),formData.append(‘key’,‘value’)
  6. 认接收最后一个实例方法
  7. set方法和append方法的区别:在属性名已经存在的情况下,set会覆盖原来的键名的值,append会保留两个值
<!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>FormData对象</title>
</head>
<body>
    <form id="form">
        <input type="text" name="username" id="" />
        <input type="password" name="password" id="" />
        <input type="button" id="btn" value="提交"/>
    </form>
    <script type="text/javascript">
    // 获取按钮
    var btn = document.querySelector('#btn')
    var form = document.querySelector('#form')
    btn.onclick = function(){
        // 将普通的html表单转换为表单对象
        let formData = new FormData(form)
        let xhr = new XMLHttpRequest()
        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>

{% folding green, 配置路由 %}

// 加入formidable模板
app.post('/formData',(req,res)=>{
    const form = new formidable.IncomingForm();
    form.parse(req,(err,fields,files)=>{
        res.send(fields)
    })
})

formData二进制上传

  1. get请求方式不能用于文件上传
<!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>FormData二进制文件上传</title>
</head>

<body>
    <input type="file" name="" id="file" />
    <script type="text/javascript">
        let file = document.querySelector('#file')
        file.onchange = function(){
            let formData = new FormData()
            formData.append('attrName',this.files[0])
            var xhr = new XMLHttpRequest()
            xhr.open('post','http://localhost:3000/up_file')
            xhr.send(formData)
            xhr.onload = function(){
                if(xhr.status==200){
                    console.log(xhr.responseText);
                }
            }
        }
    </script>
</body>

</html>

上传进度条

  1. 使用上传事件中的onprogress事件
<!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>
</head>
<style>
    .progress_warp{
        width: 800px;
        height: 40px;
        background-color: #ccc;
        border-radius: 5px;
    }
    .progress_event{
        border-radius: 5px;
        width: 0;
        height: 100%;
        color: #fff;
        background-color: rgb(53, 27, 68);
    }
</style>
<body>
    <input type="file" name="" id="file" />
    <div class="progress_warp">
        <div class="progress_event" style="width: 0%;" id="bar"></div>
    </div>
    <script type="text/javascript">
        let file = document.querySelector('#file')
        let bar = document.querySelector('#bar')
        file.onchange = function(){
            let formData = new FormData()
            formData.append('attrName',this.files[0])
            var xhr = new XMLHttpRequest()
            xhr.open('post','http://localhost:3000/up_file')
            xhr.upload.onprogress = function(e){
                // console.log(e);
                let bar_data = (e.loaded / e.total).toFixed(2) * 100 + '%'
                bar.style.width = bar_data
                bar.innerHTML = bar_data
            }
            xhr.send(formData)
            xhr.onload = function(){
                if(xhr.status==200){
                    console.log(xhr.responseText);
                }
            }
        }
    </script>
</body>
</html>

@L_502_35@图片加载预览

<!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>
</head>
<style>
    .progress_warp{
        width: 800px;
        height: 40px;
        background-color: #ccc;
        border-radius: 5px;
    }
    .Box_img{
        padding: 20px;
    }
    .Box_img img{
        width: 100px;
        border-radius: 10px;
    }
    .progress_event{
        border-radius: 5px;
        width: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 20px;
        font-weight: 550;
        margin: 10px 0;
        height: 100%;
        color: #fff;
        background-color: rgb(53, 27, 68);
    }
</style>
<body>
    <input type="file" name="" id="file" />
    <div class="Box_img">
        
    </div>
    <div class="progress_warp">
        <div class="progress_event" style="width: 0%;" id="bar"></div>
    </div>
    <script type="text/javascript">
        let file = document.querySelector('#file')
        let bar = document.querySelector('#bar')
        let Box_img = document.querySelector('.Box_img')
        file.onchange = function(){
            let formData = new FormData()
            formData.append('attrName',this.files[0])
            var xhr = new XMLHttpRequest()
            xhr.open('post','http://localhost:3000/up_file')
            xhr.upload.onprogress = function(e){
                // console.log(e);
                let bar_data = (e.loaded / e.total).toFixed(2) * 100 + '%'
                bar.style.width = bar_data
                bar.innerHTML = bar_data
            }
            xhr.send(formData)
            xhr.onload = function(){
                if(xhr.status==200){
                    // console.log(xhr.responseText);
                    // 动态创建一个图片上传文件的路径名称赋值给uploads
                    let img = document.createElement('img')
                    img.src= '/uploads' + JSON.parse(xhr.responseText).path
                    // 调用图片上传成功的事件onload
                    img.onload = function (){
                        Box_img.appendChild(img)
                    }
                }
            }
        }
    </script>
</body>
</html>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐