三、vue前後端交互(輕鬆入門vue)

輕鬆入門vue系列

六、Vue前後端交互

項目中一般結合async/await語法使用axios調用接口

1. 前後端交互模式

1. 接口調用方式

原生ajax、基於jQuery的ajax、fetch、axios

2. 傳統的URL

格式:schema://host:port/path?query#fragment

  1. schema:協議,例如http、https、ftp等。
  2. host:域名或者IP地址。
  3. port:端口,http默認端口80,可以省略。
  4. path:路徑,例如/abc/a/b/c
  5. query:查詢參數,例如uname=lisi&age=12
  6. fragment:錨點(哈希Hash),用於定位頁面的某個位置

3. Restful形式的URL

HTTP請求方式

  1. GET 查詢
  2. POST 添加
  3. PUT 修改
  4. DELETE 刪除

2. Promise的相關概念和用法

JS中常見的異步調用:定時任務、ajax、事件函數

Promise是異步編程的一種解決方案,從語法上講,Promise是一個對象,從它可以獲取異步操作的消息。

使用Promise主要有以下好處:

  • 可以避免多層異步調用嵌套問題(回調地獄)
  • Promise對象提供了簡介的API,使得控制異步操作更加容易
Promise基本用法
  • 實例化Promise對象,構造函數中傳遞函數,該函數中用於處理異步任務。

  • resolve和reject兩個(方法)參數用於處理成功和失敗兩種情況,並通過p.then獲取處理結果。

var p = new Promise(function(resolve,reject){
	//成功時調用resolve()
	//失敗時調用reject()
});
p.then(function(ret){
	//從resolve得到正常結果
},function(ret){
	//從reject得到錯誤信息
});
then參數中的函數返回值
  1. 返回Promise實例對象

返回該實例對象用於調用下一個then

p.then(function(ret){
	return new Promise(...)
}).then(...)
  1. 返回普通值

返回的普通值會直接傳遞給下一個then,通過then函數中函數的參數接收該值(底層會對返回的普通值封裝爲一個Promise使得能夠繼續調用then)

p.then(function(ret){
	return '莫逸風';	
}).then(function(ret){
	alert(ret);		//莫逸風
})
基於Promise處理多個Ajax請求demo
<script>
    //Promise基本使用,原生ajax
    function getText(url) {
        var p = new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                //readyState表示文檔狀態
                if (xhr.readyState != 4) return;
                if (xhr.readyState == 4 && xhr.status == 200){
                    //處理正常情況
                    resolve(xhr.responseText);
                }else {
                    reject('服務器錯誤');
                }
            };
            xhr.open('get',url);
            xhr.send(null);
        });
        return p;
    }
    //鏈式調用解決回調地獄,return一個新的調用就可以繼續調用新的then()了。
    getText('http://localhost:8088/saymo').then(
        function (data) {
            alert(data);
            return  getText('http://localhost:8088/sayyi');
        },function (info) {
            alert(info);
        }
    ).then(
        function (data) {
            alert(data);
            return getText('http://localhost:8088/sayfeng')
        }
    ).then(
        function (data) {
            alert(data);
        }
    );
</script>

上方調用方式會調用後端,產生跨域問題(解決方案回頭仔細研究,先放一段代碼(SpringBoot))

跨域解決方案參考

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {
    public CorsConfig(){
    }

    @Bean
    public CorsFilter corsFilter(){
        //1.添加cors配置信息
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("http://localhost:63343");
        //設置是否發送cookie信息
        config.setAllowCredentials(true);
        //設置允許請求的方式
        config.addAllowedMethod("*");
        //設置允許的header
        config.addAllowedHeader("*");

        //2.爲url添加映射路徑
        UrlBasedCorsConfigurationSource corsSource = new UrlBasedCorsConfigurationSource();
        corsSource.registerCorsConfiguration("/**",config);

        //3.返回從新定義好的corsSource
        return new CorsFilter(corsSource);
    }
}

Promise常用API
  1. 實例方法

p.then() //得到異步任務的處理結果
p.catch() //獲取異常信息
p.finally() //成功與否都會執行(尚且不是正式標準)

demo

<script>
    function foo() {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                //resolve(123)//正常情況
                reject("出錯了");//錯誤情況
            },1000)
        })
    }
    foo().then(function (data) {
        alert(data);
    }).catch(function (data) {
        alert(data);
    }).finally(function () {
        alert("結束了")
    })
    //與上面效果相同
    foo().then(function (data) {
        alert(data);
    },function (data) {
        alert(data);
    }).finally(function () {
        alert("結束了")
    })
</script>
  1. 對象方法

Promise.all()併發處理多個異步任務,所有任務都執行完成才能得到結果

Promise.race()併發處理多個異步任務,只要有一個任務完成就能得到結果

demo

<script>
    function getText(url) {
        var p = new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                //readyState表示文檔狀態
                if (xhr.readyState != 4) return;
                if (xhr.readyState == 4 && xhr.status == 200){
                    //處理正常情況
                    resolve(xhr.responseText);
                }else {
                    reject('服務器錯誤');
                }
            };
            xhr.open('get',url);
            xhr.send(null);
        });
        return p;
    }

    var p1 = getText("http://localhost:8088/saymo");
    var p2 = getText("http://localhost:8088/sayyi");
    var p3 = getText("http://localhost:8088/sayfeng");

    //result是一個數組形式的三個數據,順序和p1,p2,p3順序相同
    Promise.all([p1,p2,p3]).then(function (result) {
        alert(result);
    })
    //result返回一個數據,最快返回的一個
    Promise.race([p1,p2,p3]).then(function (result) {
        alert(result);
    })
</script>

3. fetch進行接口調用

更加簡單的數據獲取方式,功能更強大、更靈活,可以看做是xhr的升級版

基於Promise實現

fetch基本用法

語法結構

fetch(url).then(fn2)
		  .then(fn3)
		  ...
		  .cach(fn)

基本用法

fetch('/abc').then(data=>{
	return data.text();
}).then(ret=>{
	//這裏得到的纔是最終的數據
	console.log(ret);
})

demo

<script type="application/javascript">
    /**
     * Fetch API 基本用法
     */
    fetch('http://localhost:8088/saymo').then(function (data) {
        //text()方法屬於fetchAPI的一部分,它返回一份Promise實例對象,用於獲取後臺返回的數據
        return data.text();
    }).then(function (data) {
        alert(data);
    })
</script>
fetch請求參數
  1. 常用配置選項

method(String):HTTP請求方法,默認爲GET(GET、POST、PUT、DELETE)

body(String):HTTP的請求參數

headers(Object):HTTP的請求頭,默認爲{}

  1. get請求方式的參數傳遞

常規

<script>
    fetch('http://localhost:8088/sayHi?name="莫逸風',{
        method:'get'
    }).then(function (data) {
        return data.text();
    }).then(function (data) {
        alert(data);
    });
</script>

restful形式


  1. post請求方式的參數傳遞

參數form表單形式

fetch('http://localhost:8088/login',{
        method:'post',
        body:,
        headers:{
            'Content-Type':'application/x-www-form-urlencoded',
        }
    }).then(function (data) {
        return data.text();
    }).then(function (data) {
        alert(data);
    })

參數json表單形式

fetch('http://localhost:8088/login',{
        method:'post',
        body:JSON.stringify({
            name:'莫逸風',
            pass:'1234',
        }),
        headers:{
            'Content-Type':'application/json',
        }
    }).then(function (data) {
        return data.text();
    }).then(function (data) {
        alert(data);
    });
fetch響應結果

text():將返回體處理成字符串類型

json():返回結果和JSON.parse(responseText)一樣

fetch('http://localhost:8088/sayhi?name=莫逸風',{
        method:'get'
    }).then(function (data) {
        return data.json();
    }).then(function (data) {
        alert(data);
    });

4. axios進行接口調用

axios(官網:https://github.com/axios/axios)是一個基於Promise用於瀏覽器和node.js的HTTP客戶端

中文說明文檔

它具有一下特徵:

  • 支持瀏覽器和node.js
  • 支持promise
  • 能攔截請求和相應
  • 自動轉換JSON數據
axios基本用法
//去github下載文件,此js位於axios-master\dist
<script src="axios.js"></script>
<script>
    axios.get('http://localhost:8088/saymo').then(function (ret) {
        //data屬性是固定的用法,用於獲取後臺的實際數據
        alert(ret.data)
    })
</script>
axios的常用API(參數傳遞)
  • get:查詢數據
  • post:添加數據
  • put:修改數據
  • delete:刪除數據
  1. get傳遞參數

通過URL傳遞參數

axios.get('http://localhost:8088/sayhi?name=莫逸風').then(function (ret) {
        alert(ret.data)
    })

restful風格接口


通過params選項傳遞參數

axios.get('http://localhost:8088/sayhi',{
        params:{
            name:"莫逸風"
        }
    }).then(function (ret) {
        //data屬性是固定的用法,用於獲取後臺的實際數據
        alert(ret.data)
    })
  1. POST傳遞參數

通過對象傳遞參數(默認傳遞的是json格式的數據)

axios.post('http://localhost:8088/login',{
        name:"莫逸風",
        pass:"1234",
    }).then(function (ret) {
        //data屬性是固定的用法,用於獲取後臺的實際數據
        alert(ret.data)
    })

通過URLSearchParams傳遞參數(application/x-www-form-urlencoded)

var param = new URLSearchParams();
param.append('name','莫逸風');
param.append('pass','12345');
    axios.post('http://localhost:8088/login',param).then(function (ret) {
        //data屬性是固定的用法,用於獲取後臺的實際數據
        alert(ret.data)
    })
  1. axios的響應結果
  • data:實際響應回來的數據
  • headers:響應頭信息
  • status:響應狀態碼
  • statusText:響應狀態信息
axios.post('http://localhost:8088/login',param).then(function(ret){
	console.log(ret);//所有數據都包含在此對象中
	//對於json形式的響應數據可以直接獲取,不需要轉換
	alert(ret.data.name);
})
  1. axios的全局配置
axios.defaults.timeout = 3000;  //超時時間
//默認地址,再寫請求的時候只需要寫後面的路由就行了
axios.defaults.baseURL = 'http://localhost:3000/app';
axios.defaults.headers['mytoken']='aqwerwqwerqwer2ewrwe23eresdff23'//設置請求頭

demo

//配置請求的基準URL地址
axios.defaults.baseURL = 'http://localhost:8088/';
axios.get('sayhi?name=莫逸風').then(function (ret) {
    //data屬性是固定的用法,用於獲取後臺的實際數據
    alert(ret.data)
})
//注意,添加請求頭跨域需要後端設置AllowedHeader
//修改請求頭
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
  1. axios攔截器

請求攔截器

在請求發出之前設置一些信息

axios.interceptors.request.use(function (config) {
        config.baseURL = "http://localhost:8088/";
        alert(config.url);
        return config;
    },function (err) {
        console.log(err);
    })

    axios.get('sayhi?name=莫逸風').then(function (ret) {
        //data屬性是固定的用法,用於獲取後臺的實際數據
        alert(ret.data)
    })

響應攔截器(攔截器放到請求之上)

在獲取數據之前對數據做一些加工處理

axios.interceptors.response.use(function (res) {
        var data = res.data;
        return data;
    },function (err) {
        console.log(err);
    })

    axios.get('sayhi?name=莫逸風').then(function (res) {
        //data屬性是固定的用法,用於獲取後臺的實際數據
        alert(res)
    })

5. asyns/await接口調用

async/await的基本用法
  • async/await是ES7引入的語法,可以更加方便的進行異步操作

  • async關鍵字用於函數上(async函數的返回值是Promise實例對象)

  • await關鍵字用於async函數中(await可以得到異步的結果)

await後跟一個Promise對象實現異步任務,async返回值是一個Promise對象

<script src="axios.js"></script>
<script>
    axios.defaults.baseURL = 'http://localhost:8088/';
    async function queryData(){
        var ret = await axios.get('saymo');
        //alert(ret.data);
        return ret.data;
    }
    queryData().then(function (data) {
        alert(data);
    });
</script>
多個異步請求的場景

不需要.then來保證順序。

<script>
    axios.defaults.baseURL = 'http://localhost:8088/';
    async function queryData(){
        var ret = await axios.get('saymo');
        alert(ret.data);
        var ret1 = await axios.get('sayyi');
        alert(ret1.data);
        var ret2 = await axios.get('sayfeng');
        return ret2.data;
    }
    queryData().then(function (data) {
        alert(data);
    });
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章