三種實現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);
    });
}

最后成功用現在新潮的技術實現了我的網頁,還是挺美滋滋的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM