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"