1、Vuex
一、介紹
vuex是一個專門爲Vue.js設計的集中式狀態管理架構。 對於狀態,咱們把它理解爲在data中須要共享給其餘組件使用的部分數據。 Vuex和單純的全局對象有如下不一樣: 1. Vuex 的狀態存儲是響應式的。當vue組件從store中讀取狀態的時候, 若store中的狀態發生變化,那麼相應的組件也會相應的獲得高效更新。 2. 你不能直接改變store中的狀態。改變store中的狀態的惟一途徑就是顯示的 提交(commit)mutation。這樣使得咱們能夠方便的跟蹤每個狀態的變化, 從而讓咱們可以實現一些工具來幫助咱們更好的瞭解咱們的應用。
二、vuex的安裝和實例化
1. 安裝命令
-- npm install vuex
2. 實例化的兩種方式
方式一:直接在main.js裏面註冊vuex的倉庫實例 // main.js import Vue from 'vue' import App from './App' import Vuex from 'vuex' // 讓vue實例使用Vuex Vue.use(Vuex) Vue.config.productionTip = false // 實例化Vuex的倉庫,store表明倉庫 const store = new Vuex.Store({ // state存放全部的公用數據 state: { name : "bdyjy", } }); new Vue({ el: '#app', // 註冊store: store store, components: { App }, template: '<App/>' });
方式二:爲了方便維護,一般在src下面新建一個store文件夾,而後在裏面新建一個index.js // store/index.js import Vuex from "vuex" import Vue from "vue" Vue.use(Vuex); // 拋出實例化的Vuex倉庫,store表明倉庫 export default new Vuex.Store({ // state存放全部的公用數據 state: { name : "bdyjy", } }) // main.js import Vue from 'vue' import App from './App' import store from "./store/index" Vue.config.productionTip = false new Vue({ el: '#app', // 註冊store: store store, components: { App }, template: '<App/>' });
三、獲取數據
1. state
state是保存咱們data中須要共享的數據。 因爲Vuex的存儲是響應式的,從store實例中讀取狀態可使用:this.$store.state.變量名 且應該在計算屬性中返回某個狀態,由於計算屬性實時在監聽數據,數據變化了,它馬上就能知道, 若是在data屬性中返回某個狀態,那麼這個數據若是在後續變化了,它也不知道了,由於data在加載完成後就不會再監聽這個數據 示例:在某個組件中使用 // course.vue <template> <div> <h2>這是課程組件</h2> <p>我是{{name}}</p> </div> </template> <script> export default { name: "Course", // 使用計算屬性獲取倉庫裏面的name變量的值 computed: { name: function () { return this.$store.state.name } } } </script>
2. getters
有時候咱們須要從store中的state中派生出一些狀態,例如對數據進行簡單的計算。
而且不少組件都須要用到此方法,咱們要麼複製這個函數,要麼抽取到一個公共函數,多處導入。
咱們vuex提供了更加方便的方法,getters 它就像計算屬性同樣,getters的返回值會根據它的依賴被
緩存起來,只有它的依賴發生改變時,纔會從新計算。
簡單地來講,getters能夠對狀態進行二次處理
1. // store/index.js import Vuex from "vuex" import Vue from "vue" Vue.use(Vuex); // 拋出實例化的Vuex倉庫,store表明倉庫 export default new Vuex.Store({ // state存放全部的公用數據 state: { name : "bdyjy", }, // getters對state的值進行二次處理 getters: { friend: function (state) {// 接收state做爲參數 return state.name + '的朋友是:jty' } } }) 2. // 在某個組件中使用 // course.vue <template> <div> <h2>這是課程組件</h2> <p>我是{{name}}</p> <p>{{friend}}</p> </div> </template> <script> export default { name: "Course", computed: { name: function () {// 經過state取值 return this.$store.state.name }, friend: function () {// 經過getters取值 return this.$store.getters.friend } } } </script>
1. // store/index.js import Vuex from "vuex" import Vue from "vue" Vue.use(Vuex); // 拋出實例化的Vuex倉庫,store表明倉庫 export default new Vuex.Store({ // state存放全部的公用數據 state: { name : "bdyjy", }, // getters對state的值進行二次處理 getters: { friend: function (state) {// 接收state做爲參數 return state.name + '的朋友是:jty' }, play: function (state, getters) {// 接收state和getters做爲參數 // 由於要取到friend,就要state return getters.friend + '一塊兒玩' } } }) 2. // 在某個組件中使用 // course.vue <template> <div> <h2>這是課程組件</h2> <p>我是{{name}}</p> <p>{{friend}}</p> <p>{{play}}</p> </div> </template> <script> export default { name: "Course", computed: { name: function () {// 經過state取值 return this.$store.state.name }, friend: function () {// 經過getters取值 return this.$store.getters.friend }, play: function () { return this.$store.getters.play } } } </script>
四、更改store中的狀態
1. 回想一下非父子之間的組件之間是如何進行通訊的
-- 新建一個新的vue實例當作兩個組件之間通訊的橋樑 -- 一個組件使用 $emit 向這個vue實例提交事件 -- 另外一個組件在加載完成後這個vue實例經過鉤子函數mounted 使用 $on 監聽$emit提交的事件而後處理
2. vuex更改store中的狀態相似於上面的步驟
-- 經過this.$store.commit('事件名稱', '數據')提交事件到這個vuex倉庫 -- 在Vuex.Store這個實例裏面經過mutations接收提交過來的事件 -- mutations裏面的事件它會接收state爲第一個參數,後面接收其餘參數
3.示例
<template> <div> <h2>這是學位課程信息</h2> <button @click="my_click">點擊展現學位信息</button> <h3>{{degree_info}}</h3> </div> </template> <script> export default { name: "DegreeCourse", computed: { degree_info: function () { return this.$store.state.degree_info } }, methods: { // 提交事件到store my_click: function () { this.$store.commit('degree_info', '博士') } } } </script>
import Vuex from "vuex" import Vue from "vue" Vue.use(Vuex); // 拋出實例化的Vuex倉庫,store表明倉庫 export default new Vuex.Store({ state: { degree_info: '' }, // commit上來的事件在這裏進行處理 mutations: { degree_info: function (state, data) { state.degree_info = data } } })
2、axios的簡單使用
一、安裝
使用npm安裝axios -- npm install axios axios是基於promise用於瀏覽器和node.js的http客戶端
二、axios基本參數
url:請求借口地址 method:請求方式 data:請求數據 headers:請求頭 then(function(response){}):請求成功後的回調函數 catch(function(error){})請求失敗後的回調函數
三、幾種請求方法
1. get請求
// 攜帶參數的get請求 axios.get('/user?ID=12345') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
// 上面的請求能夠這樣作 axios.get('/user', { params: { ID: 12345 } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
2. post請求
axios.post('/user', { username: 'xiaoming', password: '123abcd' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
3. 執行多個併發請求
function getUserAccount() { return axios.get('/user/12345'); } function getUserPermissions() { return axios.get('/user/12345/permissions'); } axios.all([getUserAccount(), getUserPermissions()]) .then().catch();
4. axios.request(推薦使用這種)
axios.request({ method: 'post', // 請求方式:get、post、delete等等 url: '/user/12345', data: { username: 'xiaoming', password: '123abcd' } });
四、示例
1. 把axios設置成Vue對象屬性
下載好axios後,在須要使用的地方導入axios便可直接使用,axios相似於ajax,用於向後端進行數據傳輸 可是axios是不能註冊到Vue實例裏面,所以不能經過this.$axios進行使用的,由於它不是Vue實例的屬性, 可是咱們就是但願可以經過this.$axios對它進行使用呢,能夠給Vue的原型量prototype增長一個$axios屬性, 而後全部的Vue對象均可以經過this.$axios對它進行使用 // main.js import axios from "axios" Vue.prototype.$axios = axios
2. Vue代碼
<script> export default { name: "DegreeCourse", mounted(){ this.$axios.request({ url: "http://127.0.0.1:8000/test/", // 後端地址 method: "get" // 提交方式 }).then(function (response) {// then是成功後的回調函數 console.log(response); }).catch(function (error) {// catch是失敗後的回調函數 console.log(error); }) } } </script>
3. 瀏覽器的同源策略
當這個組件加載完後,會自動向後端http://127.0.0.1:8000/test/ 發送 get 請求, 可是這樣發送的請求是屬於跨域請求,因爲瀏覽器的同源策略,服務器給咱們返回的信息瀏覽器會給咱們攔截下來, 因此若是後端返回消息的時候不進行一些處理的話,前端這裏是收不到消息的而且會報錯。(先後端的域名和端口只要其中一個不同,就是跨域), 跨域的ajax請求就會被瀏覽器攔截(axios發送的也是ajax請求)。 那怎麼處理?繼續往下看..
3、CORS跨域請求介紹
一、區分簡單請求和複雜請求
HTTP方法是下列方法之一 HEAD, GET,POST HTTP頭信息不超出如下幾種字段 Accept, Accept-Language, Content-Language, Last-Event-ID Content-Type只能是下列類型中的一個 application/x-www-from-urlencoded multipart/form-data text/plain 任何一個不知足上述要求的請求,即會被認爲是複雜請求 複雜請求會先發出一個預請求,咱們也叫預檢,OPTIONS請求 也就是說,HEAD, GET,POST這三個請求,當它們知足上面的頭信息時,它們就是簡單請求,不然都是複雜請求, 好比一個get請求,可是它請求頭的Content-Type是application/json類型,那麼它也是複雜請求。 複雜請求會先發出一個OPTIONS預請求。
二、請求頭
Accept 我能解析什麼數據類型 ContentType 我給你的是什麼數據類型 數據類型 application/x-www-from-urlencoded --> form表單 multipart/form-data --> 文件格式 text/plain --> 文本 application/json --> json格式 html xml
4、跨域請求處理--jsonp
一、 原理(如今不多有人使用這種方式處理跨域請求)
咱們能夠發現,咱們使用CDN引進任何連接的時候,引進了就可使用了,可是,CDN的連接對於咱們來講也是跨域,爲何不會報錯呢?
緣由是對於script、link或img這些標籤,他們引入CDN只是發送get請求獲取資源,瀏覽器認爲這沒有風險,因此能夠正常進行請求,
而ajax能夠發送任何類型的請求,風險太大,瀏覽器就自動把它們攔截了(瀏覽器只阻止表單以及ajax請求)。
好比script標籤src想某個CDN發送get請求,拿到的全部資源就會存在script標籤內,你就能夠在script標籤內使用這些內容。
可是隻能用於發GET請求。
二、示例
// 某前端頁面代碼 <script> // 定義一個函數 function handlerResponse(data) { console.log(data) } </script> // 向後端發送請求,拿到handlerResponse函數並執行 <script src="http://127.0.0.1:8000/test/"></script>
// 某Django後端代碼 class TestView(views.View): def get(self, request): # 返回一個handlerResponse("ok")字符串 return HttpResponse('handlerResponse("ok")')
5、CORS跨域請求之簡單請求處理
一、 get跨域簡單請求
1. 報錯緣由
Access-Control-Allow-Origin --> 前端這個域不被容許接收後端的數據
2. 後端視圖函數
class TestView(views.View): def get(self, request): return HttpResponse('嘿嘿')
3. 後端中間件
from django.utils.deprecation import MiddlewareMixin class MyCores(MiddlewareMixin): def process_response(self, request, response): # 給這個響應添加響應頭 # 告訴瀏覽器我這個後端容許響應頭指定的域拿到個人響應數據(*表明全部域) response['Access-Control-Allow-Origin'] = '*' # http://localhost:8080表明只能讓這個域拿到個人數據 # response['Access-Control-Allow-Origin'] = 'http://localhost:8080' return response
4. 前端Vue
<script> export default { name: "DegreeCourse", mounted(){ this.$axios.request({ url: "http://127.0.0.1:8000/test/", // 後端地址 method: "get" // get簡單請求 // method: "post" // post簡單請求 }).then(function (response) {// then是成功後的回調函數 console.log(response); // 接收到後端response的數據是一個對象 }).catch(function (error) {// catch是失敗後的回調函數 console.log(error); }) } } </script>
二、 post跨域簡單請求
注意:先後端分離的項目沒辦法提交csrf,有些框架是能夠默認過濾跳過這個驗證,如今的話,咱們先在後端把csrf中間件註釋掉
代碼跟上面同樣,只是在前端把method的提交方式改爲post便可
6、CORS跨域請求之複雜請求處理
一、delete跨域複雜請求
1. 報錯緣由
Access-Control-Allow-Methods --> 這個請求方法不被容許
2. 後端視圖函數
class TestView(views.View): def delete(self, request): return HttpResponse("返回DELETE數據")
3. 後端中間件
class MyCores(MiddlewareMixin): def process_response(self, request, response): # 給這個響應添加響應頭 # 告訴瀏覽器我這個後端容許響應頭指定的域拿到個人響應數據(*表明全部域) response['Access-Control-Allow-Origin'] = '*' # http://localhost:8080表明只能讓這個域拿到個人數據 # response['Access-Control-Allow-Origin'] = 'http://localhost:8080' # 若是是複雜請求,會先發送OPTIONS預檢 if request.method == 'OPTIONS': # 若是是複雜請求的方法不被容許,那麼就給告訴瀏覽器我容許這個複雜請求 response["Access-Control-Allow-Methods"] = "DELETE" return response
4. 前端Vue
<script> export default { name: "DegreeCourse", mounted(){ this.$axios.request({ url: "http://127.0.0.1:8000/test/", // 後端地址 method: 'delete' // delete複雜請求 }).then(function (response) {// then是成功後的回調函數 console.log(response); // 接收到後端response的數據是一個對象 }).catch(function (error) {// catch是失敗後的回調函數 console.log(error); }); } } </script>
二、post發送複雜請求
1. 報錯緣由
Access-Control-Allow-Headers --> 這個請求頭的數據類型不被容許
2. 後端視圖函數
class TestView(views.View): def post(self, request): return HttpResponse("返回POST數據")
3. 後端中間件
class MyCores(MiddlewareMixin): def process_response(self, request, response): # 給這個響應添加響應頭 # 告訴瀏覽器我這個後端容許響應頭指定的域拿到個人響應數據(*表明全部域) response['Access-Control-Allow-Origin'] = '*' # http://localhost:8080表明只能讓這個域拿到個人數據 # response['Access-Control-Allow-Origin'] = 'http://localhost:8080' # 若是是複雜請求,會先發送OPTIONS預檢 if request.method == 'OPTIONS': # 若是是複雜請求的方法不被容許,那麼就給告訴瀏覽器我容許這個複雜請求 response["Access-Control-Allow-Methods"] = "DELETE" # 告訴瀏覽器這個請求頭的數據類型我是容許的 response["Access-Control-Allow-Headers"] = "Content-Type" return response
4. 前端Vue
<script> export default { name: "DegreeCourse", mounted(){ this.$axios.request({ url: "http://127.0.0.1:8000/test/", // 後端地址 method: 'post', // post發送複雜請求 contentType: "application/json", data: { "author": "狗屎" } }).then(function (response) {// then是成功後的回調函數 console.log(response); // 接收到後端response的數據是一個對象 }).catch(function (error) {// catch是失敗後的回調函數 console.log(error); }) } } </script>
三、總結
-- 複雜請求什麼不被容許,那麼咱們就在中間件給它設置成是容許的便可 -- 前端拿到的響應數據是一個對象,具體的值存在這個對象的data屬性裏面,取值:響應對象.data -- 響應對象還有其餘數據: config: {...} data: "後端返回的具體數據" headers: {content-type: "text/html; charset=utf-8"} request: XMLHttpRequest {…} status: 200 statusText: "OK"