vue2 -- axios

4. 經過axios實現數據請求

vue.js默認沒有提供ajax功能的。javascript

因此使用vue的時候,通常都會使用axios的插件來實現ajax與後端服務器的數據交互。css

注意,axios本質上就是javascript的ajax封裝,因此會被同源策略限制。html

下載地址:前端

https://unpkg.com/axios@0.18.0/dist/axios.js
https://unpkg.com/axios@0.18.0/dist/axios.min.js

axios提供發送請求的經常使用方法有兩個:axios.get() 和 axios.post() 。vue

增 postjava

刪 deletenode

改 putpython

查 getjquery

    // 發送get請求
    // 參數1: 必填,字符串,請求的數據接口的url地址,例如請求地址:http://www.baidu.com?id=200
    // 參數2:可選,json對象,要提供給數據接口的參數
    // 參數3:可選,json對象,請求頭信息
    axios.get('服務器的資源地址',{ // http://www.baidu.com
        params:{
            參數名:'參數值', // id: 200,
        }
    
    }).then(function (response) { // 請求成功之後的回調函數
            console.log("請求成功");
            console.log(response);
    
    }).catch(function (error) {   // 請求失敗之後的回調函數
            console.log("請求失敗");
            console.log(error.response);
    });
get請求
    // 發送post請求,參數和使用和axios.get()同樣。
    // 參數1: 必填,字符串,請求的數據接口的url地址
    // 參數2:必填,json對象,要提供給數據接口的參數,若是沒有參數,則必須使用{}
    // 參數3:可選,json對象,請求頭信息
    axios.post('服務器的資源地址',{
        username: 'xiaoming',
        password: '123456'
    },{
        responseData:"json",
    })
    .then(function (response) { // 請求成功之後的回調函數
      console.log(response);
    })
    .catch(function (error) {   // 請求失敗之後的回調函數
      console.log(error);
    });
post請求

4.1.1 json數據的語法

// json數據的對象格式:
{
    "name":"tom",
    "age":18
}

// json數據的數組格式:
["tom",18,"programmer"]

複雜的json格式數據能夠包含對象和數組的寫法。
{
  "name":"小明",
  "age":200,
  "fav":["code","eat","swim","read"],
  "son":{
    "name":"小小明",
    "age":100,
    "lve":["code","eat"],
  }
}

4.1.2 js中提供的json數據轉換方法

方法 參數 返回值 描述
stringify json對象 字符串 json對象轉成字符串
parse 字符串 json對象 字符串格式的json數據轉成json對象
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    // json語法
    let humen = {
        "username":"xiaohui",
        "password":"1234567",
        "age":20
    };

    console.log(humen);
    console.log(typeof humen);

    // JSON對象提供對json格式數據的轉換功能
    // stringify(json對象)  # 用於把json轉換成字符串
    let result = JSON.stringify(humen);
    console.log(result);
    console.log(typeof result);

    // parse(字符串類型的json數據)  # 用於把字符串轉成json對象
    let json_str = '{"password":"1123","age":20,"name":"xiaobai"}';
    console.log(json_str)
    console.log(typeof json_str)

    let json_obj = JSON.parse(json_str);
    console.log(json_obj);
    console.log(typeof json_obj)

    console.log(json_obj.age)
</script>
</body>
</html>
View Code

4.2 ajax

ajax,通常中文稱之爲:"阿賈克斯",是英文 「Async Javascript And Xml」的簡寫,譯做:異步js和xml數據傳輸數據。webpack

ajax的做用: ajax可讓js代替瀏覽器向後端程序發送http請求,與後端通訊,在用戶不知道的狀況下操做數據和信息,從而實現頁面局部刷新數據/無刷新更新數據。

因此開發中ajax是很經常使用的技術,主要用於操做後端提供的數據接口,從而實現網站的先後端分離

ajax技術的原理是實例化js的XMLHttpRequest對象,使用此對象提供的內置方法就能夠與後端進行數據通訊。

4.2.1 數據接口

數據接口,也叫api接口,表示後端提供操做數據/功能的url地址給客戶端使用。

客戶端經過發起請求向服務端提供的url地址申請操做數據【操做通常:增刪查改】

同時在工做中,大部分數據接口都不是手寫,而是經過函數庫/框架來生成。

4.2.3 ajax的使用

編寫代碼獲取接口提供的數據:

JQ版

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-1.12.4.js"></script>
    <script>
    $(function(){
        $("#btn").on("click",function(){
            $.ajax({
                // 後端程序的url地址
                url: 'http://wthrcdn.etouch.cn/weather_mini',
                // 也可使用method,提交數據的方式,默認是'GET',經常使用的還有'POST'
                type: 'get', 
                dataType: 'json',  // 返回的數據格式,經常使用的有是'json','html',"jsonp"
                data:{ // 設置發送給服務器的數據,若是是get請求,也能夠寫在url地址的?後面
                    "city":'北京'
                }
            })
            .done(function(resp) {     // 請求成功之後的操做
                console.log(resp);
            })
            .fail(function(error) {    // 請求失敗之後的操做
                console.log(error);
            });
        });
    })
    </script>
</head>
<body>
<button id="btn">點擊獲取數據</button>
</body>
</html>

總結:

1. 發送ajax請求,要經過$.ajax(),參數是對象,裏面有固定的參數名稱。
   $.ajax({
     "url":"數據接口url地址",
     "method":"http請求方式,前端只支持get和post",
     "dataType":"設置服務器返回的數據格式,經常使用的json,html,jsonp,默認值就是json",
     // 要發送給後端的數據參數,post時,數據必須寫在data,get能夠寫在data,也能夠跟在地址欄?號後面
     "data":{
       "數據名稱":"數據值",
     }
   }).then(function(resp){ // ajax請求數據成功時會自動調用then方法的匿名函數
     console.log( resp ); // 服務端返回的數據
   }).fail(function(error){ // ajax請求數據失敗時會自動調用fail方法的匿名函數
     console.log( error );
   });

2. ajax的使用每每配合事件/鉤子操做進行調用。

4.2.4 同源策略

同源策略,是瀏覽器爲了保護用戶信息安全的一種安全機制。

所謂的同源就是指通訊的兩個地址(例如服務端接口地址與瀏覽器客戶端頁面地址)之間比較,是否協議、域名(IP)和端口相同。不一樣源的客戶端腳本[javascript]在沒有明確受權的狀況下,沒有權限讀寫對方信息。

ajax本質上仍是javascript,是運行在瀏覽器中的腳本語言,因此會被受到瀏覽器的同源策略所限制。

 

tml 是否同源 緣由
http://www.oldboy.cn/user/login.html 協議、域名、端口相同
http://www.oldboy.cn/about.html 協議、域名、端口相同
https://www.oldboy.cn/user/login.html 協議不一樣 ( https和http )
http:/www.oldboy.cn:5000/user/login.html 端口 不一樣( 5000和80)
http://bbs.oldboy.cn/user/login.html 域名不一樣 ( bbs和www )

同源策略針對ajax的攔截,代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    <script src="js/axios.js"></script>
</head>
<body>
    <div id="app">
        <button @click="get_music">點擊獲取天氣</button>
    </div>
    <script>
        let vm = new Vue({
            el:"#app",
            data:{},
            methods:{
                get_music(){
                    axios.get("http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.catalogSug&query=個人中國心")
                        .then(response=>{
                            console.log(response);

                        }).catch(error=>{
                            console.log(error.response)
                    });
                }
            }
        })
    </script>
</body>
</html>

上面代碼運行錯誤以下:

Access to XMLHttpRequest at 'http://tingapi.ting.baidu.com/v1/restserver/ting?
method=baidu.ting.search.catalogSug&query=%E6%88%91%E7%9A%84%E4%B8%AD%E5%9B%BD%E5%BF%83' from origin
'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is
present on the requested resource.

上面錯誤,關鍵詞:Access-Control-Allow-Origin

只要出現這個關鍵詞,就是訪問受限。出現同源策略的攔截問題。

 

4.2.5 ajax跨域(跨源)方案之CORS

CORS是一個W3C標準,全稱是"跨域資源共享",它容許瀏覽器向跨源的後端服務器發出ajax請求,從而克服了AJAX只能同源使用的限制。

實現CORS主要依靠後端服務器中響應數據中設置響應頭信息返回的。

django的視圖

def post(request):

  response = new Response()

  response .set_header("Access-Control-Allow-Origin","*")

  return response;

// 在響應行信息裏面設置如下內容:
Access-Control-Allow-Origin: ajax所在的域名地址

Access-Control-Allow-Origin: www.oldboy.cn  # 表示只容許www.oldboy.cn域名的客戶端的ajax跨域訪問

// * 表示任意源,表示容許任意源下的客戶端的ajax均可以訪問當前服務端信息
Access-Control-Allow-Origin: *

 

 

同源策略:瀏覽器的一種保護用戶數據的一種安全機制。
瀏覽器會限制腳本語法不能跨源訪問其餘源的數據地址。
同源:判斷兩個通訊的地址之間,是否協議,域名[IP],端口一致。

ajax: http://127.0.0.1/index.html
api數據接口: http://localhost/index

這兩個是同源麼?不是同源的。是否同源的判斷依據不會根據電腦來判斷,而是經過協議、域名、端口的字符串是否來判斷。


1. ajax默認狀況下會受到同源策略的影響,一旦受到影響會報錯誤以下:
No 'Access-Control-Allow-Origin' header is present on the requested resource

2. 解決ajax只能同源訪問數據接口的方式:
  1. 在服務端的響應行中設置:
  Access-Control-Allow-Origin: 容許訪問的域名地址
  2. jsonp
  3. 是否服務端代理
   思路:經過python來請求對應的服務器接口,獲取到數據之後,

5. 組件化開發

5.1 組件[component]

組件(Component)是自定義封裝的功能。在前端開發過程當中,常常出現多個網頁的功能是重複的,並且不少不一樣的網站之間,也存在一樣的功能。

而在網頁中實現一個功能,須要使用html定義功能的內容結構,使用css聲明功能的外觀樣式,還要使用js來定義功能的特效,所以就產生了把一個功能相關的[HTML、css和javascript]代碼封裝在一塊兒組成一個總體的代碼塊封裝模式,咱們稱之爲「組件」。

 

因此,組件就是一個html網頁中的功能,通常就是一個標籤,標籤中有本身的html內容結構,css樣式和js特效。

這樣,前端人員就能夠在開發時,只須要書寫一次代碼,隨處引入便可使用。

 

組件有兩種:默認組件[全局組件] 和 單文件組件

默認組件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    <style>
    .header{
        width: 100%;
        height: 40px;
    }
    .header ul{
        list-style:none;
        padding:0;
        margin: 0;
        overflow: hidden;
    }
    .header ul li{
        width: 120px;
        height: 40px;
        line-height: 40px;
        text-align: center;
        color: #fff;
        background-color: blue;
        float: left;
        margin-right: 10px;
    }
    </style>
</head>
<body>
    <div id="app">
        <!-- 頭部 -->
        <Tou></Tou>   //引用Tou標籤
        <!-- 腳部-->
    </div>
    <script>
        // Vue.component("組件名稱",組件的相關參數[html,css,js代碼]);
        Vue.component("Tou",{    //定義一個Tou標籤
            template:`<div class="header">
                        <ul>
                            <li @click="indexHander">{{index}}</li>
                            <li>{{list}}</li>
                        </ul>
                    </div>`,

            data:function(){
                return {
                    index: "首頁",
                    list:"列表頁"
                }
            },

            methods:{
                indexHander(){
                    alert("跳轉到首頁");
                }
            }
        });

        let vm = new Vue({
            el:"#app",
            data:{}
        })
    </script>
</body>
</html>

 

6. Vue自動化工具(Vue-cli)

6.4 使用Vue-CLI初始化建立項目

6.4.1 生成項目目錄

 // 生成一個基於 webpack 模板的新項目

vue init webpack myproject

// 啓動開發服務器 ctrl+c 中止服務

cd myproject
npm run dev # 運行這個命令就能夠啓動node提供的測試http服務器

訪問: http://localhost:8080/

 

6.4.2 項目目錄結構

├── build/
├── config/
├── index.html
├── node_modules/    # 項目運行的依賴庫存儲目錄[很是大]
├── package.json     # 項目運行須要的依賴庫記錄配置
├── src/
│   ├── App.vue      # 父級組件
│   ├── assets/      # 靜態資源目錄,圖片存放在這裏
│   ├── components/  # 單文件組件保存目錄
│   └── main.js
└── static/          # 靜態資源目錄,全部的css,js等文件放在這個目錄

src 主開發目錄,要開發的單文件組件所有在這個目錄下的components目錄下

static 靜態資源目錄,全部的css,js文件放在這個文件夾

dist 項目打包發佈文件夾,最後要上線單文件項目文件都在這個文件夾中[後面打包項目,讓項目中的vue組件通過編譯變成js 代碼之後,dist就出現了]

node_modules目錄是node的包目錄,

config是配置目錄,

build是項目打包時依賴的目錄

src/router 路由,後面須要咱們在使用Router路由的時候,本身聲明.

 

6.4.3 項目執行流程圖

 

7. 單文件組件的使用

組件有兩種:普通組件、單文件組件

普通組件的缺點:

  1. html代碼是做爲js的字符串進行編寫,因此組裝和開發的時候不易理解,並且沒有高亮效果。

  2. 普通組件用在小項目中很是合適,可是複雜的大項目中,若是把更多的組件放在html文件中,那麼維護成本就會變得很是昂貴。

  3. 普通組件只是整合了js和html,可是css代碼被剝離出去了。使用的時候的時候很差處理。

 

將一個組件相關的html結構,css樣式,以及交互的JavaScript代碼從html文件中剝離出來,合成一個文件,這種文件就是單文件組件,至關於一個組件具備告終構、表現和行爲的完整功能,方便組件之間隨意組合以及組件的重用,這種文件的擴展名爲「.vue」,好比:"Home.vue"。

 

建立組件

在組件中編輯三個標籤,編寫視圖template、vm對象script標籤和css樣式代碼style。

<template>

</template>


<script>

</script>



<style>

</style>

 

7.1 template 編寫html代碼的地方

<template>
  <div id="Home">    #  全部代碼要在一個塊裏面
    <Header/>
    <div class="main">
      頁面主題內容
    </div>
    <div class="footer">
      頁面腳步內容
    </div>
  </div>
</template>

下面寫法會報錯
<template>
    <Header/>
    <div class="main">
      頁面主題內容
    </div>
    <div class="footer">
      頁面腳步內容
    </div>
</template>

7.2 script編寫vue.js代碼

<script>
  import Header from "./common/Header"
  export default {
    name:"Home", // 組件名稱,用於之後路由跳轉
    data(){      // 當前組件中須要使用的數據
      return {

      }
    },
    components:{
      Header,
    }
  }

</script>

7.3 style編寫當前組件的樣式代碼

// scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響
<style scoped>
  .header{
    height: 100px;
    line-height: 100px;
    background-color: #eee;
    text-align: center;
  }
</style>

7.3.1 在Home.vue中引入子組件

app中導入home組件,瀏覽器才能顯示home組件的內容

home組件引入header組件  (和app中引入Home相似)

 

建立保存子組件的目錄common, 在components目錄下面

在common目錄下建立Header.vue

把Home.vue的style標籤的頭部樣式放置到Header.vue

7.4 完成案例-點擊加減數字

<template>
  <div id="Home">
    <Header/>
    <div class="main">
      <p>加減數字的功能</p>
      <div class="box">
        <button @click="num++">+</button>
        <input type="text" v-model="num">
        <button @click="num--">-</button>
      </div>
    </div>
    <div class="footer">
      頁面腳步內容
    </div>
  </div>
</template>

<script>
  import Header from "./common/Header"
  export default {
    name:"Home", // 組件名稱,用於之後路由跳轉
    data(){      // 當前組件中須要使用的數據
      return {
        num:0,     // 這裏須要聲明num
      }
    },
    components:{
      Header,
    }
  }

</script>

// scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響
<style scoped>
  .header{
    height: 100px;
    line-height: 100px;
    background-color: #eee;
    text-align: center;
  }
</style>

7.4 組件的嵌套

在common目錄下,能夠建立Home頁面的子組件,例如,是Menu.vue

<template>
    <div id="menu">
      <span>{{msg}}</span>
      <p>我是menu視圖,我是主題body部分</p>
    </div>
</template>

<script>
  export default {
    name:"Menu", // 組件名稱,用於之後路由跳轉
    data(){      // 當前組件中須要使用的數據
      return {
        msg: "你們好"
      }
    }
  }

</script>

// scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響
<style scoped>

</style>

而後,在父組件 Home.vue 中調用上面聲明的子組件。

//  Menu 首字母大寫
<template>
  <div>
    <Header />
    <div class="main">
      <p>增減數字</p>
      <button @click="num++">+</button>
      <input type="text" name="" id="" v-model="num">
      <button @click="num--">-</button>
    </div>
    <Menu />   //調用
  </div>
</template>


<script>
  import Header from "./common/Header"
  import Menu from "./common/Menu"   //導入

  export default{
    name: "Home",
    data(){
      return{
        num:0,
        }
      },
      components:{
        Header,Menu    //聲明
    }
  }
</script>

<style>

</style>

最後,父組件被App.vue調用.就能夠看到頁面效果.

7.5 傳遞數據

能夠經過props屬性來進行傳遞.

傳遞數據三個步驟:

  1. 在父組件中,調用子組件的組名處,使用屬性值的方式往下傳遞數

    <template>
    <
    Menu :mynum="num" title="home裏面寫的數據"/>
    </template>

    # 上面表示在父組件調用Menu子組件的時候傳遞了2個數據:
    若是要傳遞變量[變量能夠各類類型的數據],屬性名左邊必須加上冒號:,同時,屬性名是自定義的,會在子組件中使用。
    若是要傳遞普通字符串數據,則不須要加上冒號:

  2. 在子組件中接受上面父組件傳遞的數據,須要在vm組件對象中,使用props屬性類接受。
    <script>
      export default {
        name:"Menu",
        props:["mynum","title"],   //用props接收值
        data: function(){
          return {
            msg:"這是Menu組件裏面的菜單",
          }
        }
      }
    </script>

 在子組件中的template中使用父組件傳遞過來的數據.

<template>
    <div id="menu">
      <span>{{msg}},{{title}}</span>
      <div>hello,{{mynum}}</div>
  </div>
</template>

使用父組件傳遞數據給子組件時, 注意一下幾點:

  1. 傳遞數據是變量,則須要在屬性左邊添加冒號.

    傳遞數據是變量,這種數據稱之爲"動態數據傳遞"

    傳遞數據不是變量,而是數值或者字符串,這種數據稱之爲"靜態數據傳遞"

  2. 父組件中修改了數據,在子組件中會被同步修改,可是,子組件中的數據修改了,是不會影響到父組件中的數據.

    這種狀況,在開發時,也被稱爲"單向數據流"

  1. 事實上,咱們若是要在子組件中把數據傳遞給父組件,也能夠完成的。

    經過事件冒泡的方式,進行數據傳遞

    在vue中提供的this.$emit()方法進行給咱們傳遞數據

 

8. 在組件中使用axios獲取數據

默認狀況下,咱們的項目中並無對axios包的支持,因此咱們須要下載安裝。

在項目根目錄中使用 npm安裝包在命令行下執行安裝包的命令:

npm install axios

接着在main.js文件中,導入axios並把axios對象 掛載到vue屬性中多爲一個子對象,這樣咱們才能在組件中使用。

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App' // 這裏表示從別的目錄下導入 單文件組件
import axios from 'axios'; // 從node_modules目錄中導入包
Vue.config.productionTip = false

Vue.prototype.$http = axios; // 把對象掛載vue中  $http 能夠本身定義名稱

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
});

8.1 在組件中使用axios獲取數據

代碼編寫在Heaer.vue子組件中

<template>
    <div id="Header" class="header">
      {{message}}
      <p>num: <input type="text" v-model="num"></p>
      <p>深圳的天氣狀況: {{weather_info}}</p>
    </div>
</template>

<script>
  export default {
    name:"Header", // 組件名稱,用於之後路由跳轉
    props:["num"],
    data(){      // 當前組件中須要使用的數據
      return {
        message:"頁面頭部",
        weather_info:"",
      }
    },
    // 鉤子方法,在頁面中vue掛在data數據之後,自動執行
    created() {
      // 使用axios發送請求獲取數據
      this.$http.get("http://wthrcdn.etouch.cn/weather_mini?city=深圳").then(response=>{
        console.log(response.data);
        console.log(response.data.data.ganmao);
        this.weather_info = response.data.data.ganmao;
      }).catch(error=>{

      });
    }

  }

</script>

// scoped 表示當前style的樣式只做用於當前組件的template代碼中,其餘地方不會被影響
<style scoped>
  .header{
    height: 100px;
    line-height: 100px;
    background-color: #eee;
    text-align: center;
  }
</style>

使用的時候,由於本質上來講,咱們仍是原來的axios,因此也會收到同源策略的影響。

後面開發項目的時候,咱們會使用cors來解決跨域的問題

相關文章
相關標籤/搜索