• 三种实现AJAX的方法以及Vue和axios结合使用的坑


    前言

    之前曾经想自己写一个天气的App,并找到了一个免费的天气数据接口的服务商——和风天气,当时也不懂怎么发HTTP请求,而且也只会用Java语言,看到官方文档里面有一个Java代码示例,就复制了一下在自己电脑上调通。一开始是在控制台输出天气数据的,后来用Swing写了一个图形化界面并放置数据,但也就到此为止了,并没有什么实用价值。

    最近学习了一下前端的相关知识,发现像和风天气这样的数据接口,根本不需要用到像Java这样的大型语言,只需在网页端用Javascript发HTTP请求就能获得JSON数据,之后再渲染到HTML网页,大大节省了资源利用和开发时间,并了解到开发这样的网页最适合的方式就是使用AJAX,因为它可以实现网页的局部更新。这样我就可以实现如下的业务场景:输入想要搜索的城市,点击搜索,下面显示出该城市的天气信息,而不影响页面的其他内容。有时候JS调用AJAX请求会有跨域问题,但和风天气的数据接口并没有这个问题。

    具体场景

    界面如图:

    界面

    在输入框输入城市名,点击搜索按钮,可以在下面显示出各项数据(从接口获得)。

    大致的HTML代码如下:

    <div class="container ">
    	<div class="text-center">
    	<h1>天气查询</h1>
        <div class="form-inline row">
            <input type="text" class="form-control" placeholder="关键字" id="input-location"/>
            <button class="btn btn-primary" onclick="loadBasic();loadAir();">搜 索</button>
        </div>
    	</div>
        <table class="table" >
            <thead>
            <tr>
                <th>位置</th>
                <th>温度</th>
                <th>湿度</th>
                <th>能见度</th>
                <th>空气质量指数</th>
                <th>更新时间</th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td id="loc"></td>
                <td id="tmp"></td>
                <td id="hum"></td>
                <td id="vis"></td>
                <td id="aqi"></td>
                <td id="update"></td>
            </tr>
            </tbody>
        </table>
    </div> 
    

    和风天气返回的json数据示例

    {
        "HeWeather6": [{
            "basic": {
                "cid": "CN101010100",
                "location": "北京",
                "parent_city": "北京",
                "admin_area": "北京",
                "cnty": "中国",
                "lat": "39.90498734",
                "lon": "116.4052887",
                "tz": "+8.00"
            },
            "update": {
                "loc": "2019-06-05 21:57",
                "utc": "2019-06-05 13:57"
            },
            "status": "ok",
            "now": {
                "cloud": "91",
                "cond_code": "104",
                "cond_txt": "阴",
                "fl": "23",
                "hum": "55",
                "pcpn": "0.0",
                "pres": "1005",
                "tmp": "23",
                "vis": "16",
                "wind_deg": "249",
                "wind_dir": "西南风",
                "wind_sc": "2",
                "wind_spd": "7"
            }
        }]
    }
    

    下面主要描述三种我自己探索经历中使用AJAX的方法

    传统AJAX

    原生JS就支持AJAX,这里我借鉴了一部分网上的教程里的代码,具体的代码如下:

    function loadBasic() //获取基本天气信息
    {        
        var xmlhttp;
        if (window.XMLHttpRequest)
        {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
        }
        else
        {// code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
        xmlhttp.onreadystatechange=function()
        {
        if (xmlhttp.readyState==4 && xmlhttp.status==200)
            {
            var str=xmlhttp.responseText;
            var obj=JSON.parse(str);
            document.getElementById("loc").innerHTML=obj.HeWeather6[0].basic.location;
            document.getElementById("tmp").innerHTML=obj.HeWeather6[0].now.tmp;
            document.getElementById("hum").innerHTML=obj.HeWeather6[0].now.hum+"%";
            document.getElementById("vis").innerHTML=obj.HeWeather6[0].now.vis+"km";
            }
        }
        var location=document.getElementById("input-location").value;
        xmlhttp.open("GET","https://free-api.heweather.net/s6/weather/now?location="+location+"&key=我的和风天气key",true);
        xmlhttp.send();
    }
            
    function loadAir() //获取空气质量信息
    {       
        //仿照上面的方法
    }
    

    原生AJAX的确能够满足业务场景的要求,但操作较为繁琐,于是我又找到了另一种方法——axios

    axios

    axios是对原生AJAX的封装,使用时需要导入axios.js文件包。相较于原生JS,axios使用起来更为简便,同样的功能代码如下:

    function loadBasic() //获取基本天气信息
    {
        var location=document.getElementById("input-location").value;
        axios.get('https://free-api.heweather.net/s6/weather/now?location='+location+'&key=89d49e32a26d4067822c9ed361231e2d')
        .then(function (response) {
            document.getElementById("loc").innerHTML=response.data.HeWeather6[0].basic.location;
            document.getElementById("tmp").innerHTML=response.data.HeWeather6[0].now.tmp;
            document.getElementById("hum").innerHTML=response.data.HeWeather6[0].now.hum+"%";
            document.getElementById("vis").innerHTML=response.data.HeWeather6[0].now.vis+"km";
        })
        .catch(function (error) {
            console.log(error);
        });
    }
    function loadAir() //获取空气质量信息
    {       
        //仿照上面的方法
    }
    

    axios是Vue.js推荐使用的实现AJAX功能的工具,Vue.js的名气我就不说了,在前端那就是如神器一般的存在。但是我们这里并没有用到Vue.js。让Vue.js和axios结合起来该怎么使用呢,请看下文

    Vue.js和axios结合

    一开始照着网上的教程和自己的摸索,我是这么写的(错误示范):

    var vm=new Vue({
        el: '#app',
        data: {
            inputlocation:' ',
            loc:'',
            tmp:'',
            hum:'',
            vis:'',
            aqi:'',
            update:''
            
        },
        methods: {
            loadBasic:function(){
                axios.get('https://free-api.heweather.net/s6/weather/now',{
                    params:{
                        location:this.inputlocation,
                        key:'89d49e32a26d4067822c9ed361231e2d'
                    }
                })
                .then(function (response) {
                    this.loc=(response.data.HeWeather6[0].basic.location);
                    this.tmp=response.data.HeWeather6[0].now.tmp;
                    this.hum=response.data.HeWeather6[0].now.hum+"%";
                    this.vis=response.data.HeWeather6[0].now.vis+"km";
                })
                .catch(function (error) {
                    console.log(error);
                });
            },
            loadAir:function(){
                axios.get('https://free-api.heweather.net/s6/air/now',{
                    params:{
                        location:this.inputlocation,
                        key:'89d49e32a26d4067822c9ed361231e2d'
                    }
                })
                .then(function (response) {
                    this.update=response.data.HeWeather6[0].update.loc;
                    this.aqi=response.data.HeWeather6[0].air_now_city.aqi;
                })
                .catch(function (error) {
                    console.log(error);
                });
            }
    
        }
    })
    

    同时HTML也有较大的改动,我在此列出:

    <div class="container " id="app">
    	<div class="text-center">
    	<h1>天气查询</h1>
        <div class="form-inline row">
            <input type="text" class="form-control" placeholder="关键字" id="input-location" v-model="inputlocation"/>
            <button class="btn btn-primary" @click="loadBasic();loadAir()">搜 索</button>
        </div>
    	</div>
        <table class="table" >
            <thead>
            <tr>
                <th>位置</th>
                <th>温度</th>
                <th>湿度</th>
                <th>能见度</th>
                <th>空气质量指数</th>
                <th>更新时间</th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td id="loc">{{loc}}</td>
                <td id="tmp">{{tmp}}</td>
                <td id="hum">{{hum}}</td>
                <td id="vis">{{vis}}</td>
                <td id="aqi">{{aqi}}</td>
                <td id="update">{{update}}</td>
            </tr>
            </tbody>
        </table>
    </div> 
    

    但是发现不能成功实现,而且确认数据应该是绑定上了,甚至在控制台手动执行axios方法(将this改成vm)都能成功。后来经过一番搜索,再加上室友的神助攻,发现原来axios方法里面的this已经不是指向vm对象了,因为已经经过了两层方法。这种情况在非严格模式下this会被当做window,在严格模式下this不可用。解决这个问题的方法有两种

    1. 在第一层方法内指定that=this,在第二层方法内把this替换成that
    2. 使用ES6的箭头函数

    第一种方法的代码如下:

    loadBasic:function(){
        let that = this;    //如果在response方法里用this,会错误
        axios.get('https://free-api.heweather.net/s6/weather/now',{
            params:{
                location:this.inputlocation,
                key:'89d49e32a26d4067822c9ed361231e2d'
            }
        })
        .then(function (response) {
            that.loc=(response.data.HeWeather6[0].basic.location);
            that.tmp=response.data.HeWeather6[0].now.tmp;
            that.hum=response.data.HeWeather6[0].now.hum+"%";
            that.vis=response.data.HeWeather6[0].now.vis+"km";
        })
        .catch(function (error) {
            console.log(error);
        });
    },
    loadAir:function(){
        let that = this;    //如果在response方法里用this,会错误
        axios.get('https://free-api.heweather.net/s6/air/now',{
            params:{
                location:this.inputlocation,
                key:'89d49e32a26d4067822c9ed361231e2d'
            }
        })
        .then(function (response) {
            that.update=response.data.HeWeather6[0].update.loc;
            that.aqi=response.data.HeWeather6[0].air_now_city.aqi;
        })
        .catch(function (error) {
            console.log(error);
        });
    }
    

    第二种方法的代码如下

    loadBasic:function(){
        axios.get('https://free-api.heweather.net/s6/weather/now',{
            params:{
                location:this.inputlocation,
                key:'89d49e32a26d4067822c9ed361231e2d'
            }
        })
        .then((response)=> {
            this.loc=(response.data.HeWeather6[0].basic.location);
            this.tmp=response.data.HeWeather6[0].now.tmp;
            this.hum=response.data.HeWeather6[0].now.hum+"%";
            this.vis=response.data.HeWeather6[0].now.vis+"km";
        })
        .catch(function (error) {
            console.log(error);
        });
    },
    loadAir:function(){
        axios.get('https://free-api.heweather.net/s6/air/now',{
            params:{
                location:this.inputlocation,
                key:'89d49e32a26d4067822c9ed361231e2d'
            }
        })
        .then((response)=> {
            this.update=response.data.HeWeather6[0].update.loc;
            this.aqi=response.data.HeWeather6[0].air_now_city.aqi;
        })
        .catch(function(error) {
            console.log(error);
        });
    }
    

    最后成功用现在新潮的技术实现了我的网页,还是挺美滋滋的。

  • 相关阅读:
    JFinal连接多个数据库
    ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061) net start mysql服务名无效
    oracle中文显示为问号
    IDEA开发环境的设置约定
    WSL distro导入导出
    Linux服务器的x11图形模式方式远程管理参考
    WSL Linux 的 Windows 子系统[笔记]
    devops-cd之esxi和docker实战
    devops-cd之vagrant virtualbox实战
    ansible高级使用知识点
  • 原文地址:https://www.cnblogs.com/aopstudio/p/10982467.html
Copyright © 2020-2023  润新知