(二十七)、Vue中的ajax
1.Vue项目中常用的2个ajax库
(1).vue-resource
- vue插件,非官方库,vue1.x使用广泛、现在已经弃用。
(2).axios
- 通用的ajax请求库,官方推荐,vue2.x使用广泛。
2.解决开发环境Ajax跨域问题
- 使用代理服务器
3.Github搜索案列_axios_全局总线
(1).静态资源
App.vue
<template> <div> <div class="container"> <section class="jumbotron"> <h3 class="jumbotron-heading">Search Github Users</h3> <div> <input type="text" placeholder="enter the name you search"/> <button>Search</button> </div> </section> <div class="row"> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> </div> </div> </div> </template> <script> export default { name:'App' } </script> <style> .album { min-height: 50rem; /* Can be removed; just added for demo purposes */ padding-top: 3rem; padding-bottom: 3rem; background-color: #f7f7f7; } .card { float: left; /* 这个目的是一行放三个 */ width: 33.333%; padding: .75rem; /* 这个意思是每个div的行距是2分米 */ margin-bottom: 2rem; border: 1px solid #efefef; text-align: center; } .card > img { margin-bottom: .75rem; border-radius: 100px; } .card-text { font-size: 85%; } </style>
bootstrap.css
太多了这里不展示 • 1
public: 就是我们引入第三方库的位置 比如:"layui.js,bootstrap.js"
<%= BASE_URL %> 相当于帮助我们找到了pubilic/ • 1
(2).静态资源设置成组件
App.vue
<template> <div> <div class="container"> <Searcher/> <List/> </div> </div> </template> <script> import Searcher from './components/Searcher.vue' import List from './components/List.vue' export default { name:'App', components:{ Searcher, List } } </script> <style> </style>
Searcher.vue
<template> <div> <section class="jumbotron"> <h3 class="jumbotron-heading">Search Github Users</h3> <div> <input type="text" placeholder="enter the name you search"/> <button>Search</button> </div> </section> </div> </template> <script> export default { name:'Searcher' } </script> <style> </style>
List.vue
<template> <div> <div class="row"> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> </div> </div> </template> <script scoped> export default { name:'List' } </script> <style> .album { min-height: 50rem; /* Can be removed; just added for demo purposes */ padding-top: 3rem; padding-bottom: 3rem; background-color: #f7f7f7; } .card { /* 从哪里开始排序 */ float: left; /* 这个目的是一行放三个 */ width: 33.333%; padding: .75rem; /* 这个意思是每个div的行距是2分米 */ margin-bottom: 2rem; border: 1px solid #efefef; text-align: center; } .card > img { margin-bottom: .75rem; /* 控制图片的范围 */ border-radius: 100px; } .card-text { font-size: 95%; } </style>
(3).github搜索案列_发送请求
下载axios的插件。在控制台我们添加 axios
npm add axios
接口地址: https://api.github.com/search/users?q=xxx
注册全局事件总线
import Vue from 'vue' // 引入阉割版本的vue import App from './App.vue' // 引入App.vue组件 Vue.config.productionTip = false; new Vue({ // 1.安装全局事件总线 beforeCreate(){ Vue.prototype.$bus=this; }, render:h=>h(App) }).$mount('#app');
App.vue
<template> <div> <div class="container"> <Searcher/> <List/> </div> </div> </template> <script> import Searcher from './components/Searcher.vue' import List from './components/List.vue' export default { name:'App', components:{ Searcher, List } } </script> <style> </style>
List.vue
1.接受兄弟List传递过来的数据 methods: { accept_message(x){ console.log('搜索的信息->>>>',x) } }, mounted() { this.$bus.$on('list_A',this.accept_message) },
<template> <div> <div class="row"> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> <div class="card"> <a href="https://github.com/reactjs" target="_blank"> <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/> </a> <p class="card-text">reactjs</p> </div> </div> </div> </template> <script scoped> export default { name:'List', data() { return { lists:[], } }, methods: { accept_message(x){ // this.lists=x; console.log('搜索的信息->>>>',x) } }, mounted() { this.$bus.$on('list_A',this.accept_message) }, } </script> <style> .album { min-height: 50rem; /* Can be removed; just added for demo purposes */ padding-top: 3rem; padding-bottom: 3rem; background-color: #f7f7f7; } .card { /* 从哪里开始排序 */ float: left; /* 这个目的是一行放三个 */ width: 33.333%; padding: .75rem; /* 这个意思是每个div的行距是2分米 */ margin-bottom: 2rem; border: 1px solid #efefef; text-align: center; } .card > img { margin-bottom: .75rem; /* 控制图片的范围 */ border-radius: 100px; } .card-text { font-size: 95%; } </style>
Searcher.vue
在搜索的组件中: 我们需要在方法上添加 async 标注着这个方法是异步方法。然后通过axios.get进行获取某一个接口, 第一个参数是异步请求的网址,第二个是请求网址的参数。response.data是获取回调的信息。然后需要向兄弟组件中传递我们回调成功的数据。 methods: { async Searcher(){ // TODO: 拼接参数: 左边的是网址右边是拼接参数。 里面的对象名一定要是params。 // ! https://api.github.com/search/users?q=xxx try { const response= await axios.get('https://api.github.com/search/users',{params:{q:this.key_words}}) const {items}=response.data; // 假如信息调用成功我们就回显 console.log(items) // 展示我们查询到的信息 this.$bus.$emit('list_A',items) } catch (error) { console.log('信息调用失败了!!') } } },
<template> <div> <section class="jumbotron"> <h3 class="jumbotron-heading">Search Github Users</h3> <div> <input type="text" placeholder="enter the name you search" v-model="key_words"/> <button @click="Searcher">Search</button> </div> </section> </div> </template> <script> // TODO: 引入我们添加得axios import axios from 'axios' export default { name:'Searcher', data() { return { key_words:'' } }, methods: { async Searcher(){ // TODO: 拼接参数: 左边的是网址右边是拼接参数。 里面的对象名一定要是params。 // ! https://api.github.com/search/users?q=xxx try { const response= await axios.get('https://api.github.com/search/users',{params:{q:this.key_words}}) const {items}=response.data; // 假如信息调用成功我们就回显 console.log(items) // 展示我们查询到的信息 this.$bus.$emit('list_A',items) } catch (error) { console.log('信息调用失败了!!') } } }, } </script> <style> </style>
(4).github搜索案列完成
这里我们新增了是否是第一次访问、是否正在加载中、和加载后数据的处理
App.vue
<template> <div> <div class="container"> <Searcher/> <List/> </div> </div> </template> <script> import Searcher from './components/Searcher.vue' import List from './components/List.vue' export default { name:'App', components:{ Searcher, List } } </script> <style> </style>
Searcher.vue
这里的参数我们传递的是: 对象。对象里面的对象名要和接受这个数据组件里面的data对象名要一致。 分别触发三次: 分别是-> 请求之前、请求成功之后、请求失败之后 methods: { async Searcher(){ // 请求之前通知List更新它的data this.$bus.$emit('list_A',{isFirst:false,isLoading:true}) // TODO: 拼接参数: 左边的是网址右边是拼接参数。 里面的对象名一定要是params。 // ! https://api.github.com/search/users?q=xxx try { const response= await axios.get('https://api.github.com/search/users',{params:{q:this.key_words}}) const {items}=response.data; // 假如信息调用成功我们就回显 console.log(items) // 展示我们查询到的信息 // 请求成功之后,通知List组件更新它的data this.$bus.$emit('list_A',{isLoading:false,lists:items}) } catch (error) { // 请求失败周会 this.$bus.$emit('list_A',{isLoading:false,lists:[],errMsg:error.message}) console.log('信息调用失败了!!') } } },
<template> <div> <section class="jumbotron"> <h3 class="jumbotron-heading">Search Github Users</h3> <div> <input type="text" placeholder="enter the name you search" v-model="key_words"/> <button @click="Searcher">Search</button> </div> </section> </div> </template> <script> // TODO: 引入我们添加得axios import axios from 'axios' export default { name:'Searcher', data() { return { key_words:'' } }, methods: { async Searcher(){ // 请求之前通知list_A更新它的data this.$bus.$emit('list_A',{isFirst:false,isLoading:true}) // TODO: 拼接参数: 左边的是网址右边是拼接参数。 里面的对象名一定要是params。 // ! https://api.github.com/search/users?q=xxx try { const response= await axios.get('https://api.github.com/search/users',{params:{q:this.key_words}}) const {items}=response.data; // 假如信息调用成功我们就回显 console.log(items) // 展示我们查询到的信息 // 请求成功之后,通知List组件更新它的data this.$bus.$emit('list_A',{isLoading:false,lists:items}) } catch (error) { // 请求失败周会 this.$bus.$emit('list_A',{isLoading:false,lists:[],errMsg:error.message}) console.log('信息调用失败了!!') } } }, } </script> <style> </style>
Lists.vue
接受数据的时候: 1. {...this.listInfo,...x} 就是把第一个的key-value替换成第二个key-value。只替换不一样的。 2. 三个点对象 代表展开成key-value形式。 3. {...对象名,属性名:值} 就是将第一个对象的属性名替换成右边的假如不同的情况下。 methods: { // 我们接受的是一个对象 accept_message(x){ console.log('搜索的信息->>>>',x); this.listInfo={...this.listInfo,...x} // 假如左边的key-value与右边的key-value不一样,就替换成右边的 } }, mounted() { this.$bus.$on('list_A',this.accept_message) }, }
<template> <div> <div class="row"> <h2 v-show="listInfo.isFirst">第一次请求</h2> <h2 v-show="listInfo.isLoading">正在加载....</h2> <div class="card" v-for="list_obj in listInfo.lists" :key="list_obj.id"> <a :href="list_obj.html_url" target="_blank"> <img :src="list_obj.avatar_url" style='width: 100px'/> </a> <p class="card-text">{{list_obj.login}}</p> </div> </div> </div> </template> <script scoped> export default { name:'List', data() { return { listInfo:{ lists:[], // 是否是第一次请求 isFirst:true, // 是否正在加载 isLoading:false, errMsg:'' } } }, methods: { // 我们接受的是一个对象 accept_message(x){ console.log('搜索的信息->>>>',x); this.listInfo={...this.listInfo,...x} // 假如左边的key-value与右边的key-value不一样,就替换成右边的 } }, mounted() { this.$bus.$on('list_A',this.accept_message) }, } </script> <style> .card { /* 从哪里开始排序 */ float: left; /* 这个目的是一行放三个 */ width: 33.333%; padding: .75rem; /* 这个意思是每个div的行距是2分米 */ margin-bottom: 2rem; /* 边框 */ border: 1px solid #efefef; text-align: center; } /* 图片的大小 */ .card > img { margin-bottom: .75rem; /* 控制图片的范围 */ border-radius: 100px; } /* 文本大小 */ .card-text { font-size: 95%; } </style>
4.Github搜索案列_订阅与发布_axios
安装订阅与发布的插件
npm add pubsub-js
引入订阅与发布
// 引入订阅与发布的插件 import PubSub from 'pubsub-js'
App.vue
<template> <div> <div class="container"> <Searcher/> <List/> </div> </div> </template> <script> import Searcher from './components/Searcher.vue' import List from './components/List.vue' export default { name:'App', components:{ Searcher, List } } </script> <style> </style>
Searcher.vue 发送者
// TODO: 引入我们添加得axios import axios from 'axios' // 引入订阅与发布的插件 import PubSub from 'pubsub-js' 发送信息 // this.$bus.$emit('list_A',{isFirst:false,isLoading:true}) PubSub.publish('list_A',{isFirst:false,isLoading:true})
<template> <div> <section class="jumbotron"> <h3 class="jumbotron-heading">Search Github Users</h3> <div> <input type="text" placeholder="enter the name you search" v-model="key_words"/> <button @click="Searcher">Search</button> </div> </section> </div> </template> <script> // TODO: 引入我们添加得axios import axios from 'axios' // 引入订阅与发布的插件 import PubSub from 'pubsub-js' export default { name:'Searcher', data() { return { key_words:'' } }, methods: { async Searcher(){ // 请求之前通知List更新它的data // this.$bus.$emit('list_A',{isFirst:false,isLoading:true}) PubSub.publish('list_A',{isFirst:false,isLoading:true}) // TODO: 拼接参数: 左边的是网址右边是拼接参数。 里面的对象名一定要是params。 // ! https://api.github.com/search/users?q=xxx try { const response= await axios.get('https://api.github.com/search/users',{params:{q:this.key_words}}) const {items}=response.data; // 假如信息调用成功我们就回显 console.log(items) // 展示我们查询到的信息 // 请求成功之后,通知List组件更新它的data // this.$bus.$emit('list_A',{isLoading:false,lists:items}) PubSub.publish('list_A',{isLoading:false,lists:items}) } catch (error) { // 请求失败周会 // this.$bus.$emit('list_A',{isLoading:false,lists:[],errMsg:error.message}) PubSub.publish('list_A',{isLoading:false,lists:[],errMsg:error.message}) console.log('信息调用失败了!!') } } }, } </script> <style> </style>
List.vue 订阅者
// 引入订阅与发布的插件 import PubSub from 'pubsub-js' // 订阅 mounted() { this.token=PubSub.subscribe('list_A',this.accept_message) }, // 取消订阅 beforeDestroy(){ PubSub.unsubscribe(this.token); }
<template> <div> <div class="row"> <h2 v-show="listInfo.isFirst">第一次请求</h2> <h2 v-show="listInfo.isLoading">正在加载....</h2> <div class="card" v-for="list_obj in listInfo.lists" :key="list_obj.id"> <a :href="list_obj.html_url" target="_blank"> <img :src="list_obj.avatar_url" style='width: 100px'/> </a> <p class="card-text">{{list_obj.login}}</p> </div> </div> </div> </template> <script scoped> // 引入订阅与发布的插件 import PubSub from 'pubsub-js' export default { name:'List', data() { return { listInfo:{ lists:[], // 是否是第一次请求 isFirst:true, // 是否正在加载 isLoading:false, errMsg:'' } } }, methods: { // 我们接受的是一个对象 accept_message(msg,x){ // TODO: 发布与订阅模式中,接收信息会收到两个参数,第一个是msg,第二个才是数据。 console.log('搜索的信息->>>>',x); this.listInfo={...this.listInfo,...x} // 假如左边的key-value与右边的key-value不一样,就替换成右边的 } }, mounted() { this.token=PubSub.subscribe('list_A',this.accept_message) }, beforeDestroy(){ // 取消订阅 PubSub.unsubscribe(this.token); } } </script> <style> .card { /* 从哪里开始排序 */ float: left; /* 这个目的是一行放三个 */ width: 33.333%; padding: .75rem; /* 这个意思是每个div的行距是2分米 */ margin-bottom: 2rem; /* 边框 */ border: 1px solid #efefef; text-align: center; } /* 图片的大小 */ .card > img { margin-bottom: .75rem; /* 控制图片的范围 */ border-radius: 100px; } /* 文本大小 */ .card-text { font-size: 95%; } </style>
5.Github搜索案列_vue-resource
它是vue的官方插件…
安装vue-resorce
npm add vue-resource
引用Vue-resorce
因为是VUE的官方库、所以我们需要使用到Vue.use
import Vue from "Vue" import VueResource from 'vue-resource' Vue.use(VueResource)
引入Vue插件之后: Vue的原型上会新增一个 $http
main.js
import Vue from 'vue' // 引入阉割版本的vue import App from './App.vue' // 引入App.vue组件 import VueResource from 'vue-resource' Vue.use(VueResource) Vue.config.productionTip = false; new Vue({ // 1.安装全局事件总线 beforeCreate(){ Vue.prototype.$bus=this; }, render:h=>h(App) }).$mount('#app');
App.vue
<template> <div> <div class="container"> <Searcher/> <List/> </div> </div> </template> <script> import Searcher from './components/Searcher.vue' import List from './components/List.vue' export default { name:'App', components:{ Searcher, List } } </script> <style> </style>
Searcher.vue
const response= await this.$http.get('https://api.github.com/search/users',{params:{q:this.key_words}}) • 1
<template> <div> <section class="jumbotron"> <h3 class="jumbotron-heading">Search Github Users</h3> <div> <input type="text" placeholder="enter the name you search" v-model="key_words"/> <button @click="Searcher">Search</button> </div> </section> </div> </template> <script> // TODO: 引入我们添加得axios import axios from 'axios' // 引入订阅与发布的插件 import PubSub from 'pubsub-js' export default { name:'Searcher', data() { return { key_words:'' } }, methods: { async Searcher(){ // 请求之前通知List更新它的data // this.$bus.$emit('list_A',{isFirst:false,isLoading:true}) PubSub.publish('list_A',{isFirst:false,isLoading:true}) // TODO: 拼接参数: 左边的是网址右边是拼接参数。 里面的对象名一定要是params。 // ! https://api.github.com/search/users?q=xxx try { const response= await this.$http.get('https://api.github.com/search/users',{params:{q:this.key_words}}) const {items}=response.data; // 假如信息调用成功我们就回显 console.log(items) // 展示我们查询到的信息 // 请求成功之后,通知List组件更新它的data // this.$bus.$emit('list_A',{isLoading:false,lists:items}) PubSub.publish('list_A',{isLoading:false,lists:items}) } catch (error) { // 请求失败周会 // this.$bus.$emit('list_A',{isLoading:false,lists:[],errMsg:error.message}) PubSub.publish('list_A',{isLoading:false,lists:[],errMsg:error.message}) console.log('信息调用失败了!!') } } }, } </script> <style> </style>
List.vue
<template> <div> <div class="row"> <h2 v-show="listInfo.isFirst">第一次请求</h2> <h2 v-show="listInfo.isLoading">正在加载....</h2> <div class="card" v-for="list_obj in listInfo.lists" :key="list_obj.id"> <a :href="list_obj.html_url" target="_blank"> <img :src="list_obj.avatar_url" style='width: 100px'/> </a> <p class="card-text">{{list_obj.login}}</p> </div> </div> </div> </template> <script scoped> // 引入订阅与发布的插件 import PubSub from 'pubsub-js' export default { name:'List', data() { return { listInfo:{ lists:[], // 是否是第一次请求 isFirst:true, // 是否正在加载 isLoading:false, errMsg:'' } } }, methods: { // 我们接受的是一个对象 accept_message(msg,x){ // TODO: 发布与订阅模式中,接收信息会收到两个参数,第一个是msg,第二个才是数据。 console.log('搜索的信息->>>>',x); this.listInfo={...this.listInfo,...x} // 假如左边的key-value与右边的key-value不一样,就替换成右边的 } }, mounted() { this.token=PubSub.subscribe('list_A',this.accept_message) }, beforeDestroy(){ // 取消订阅 PubSub.unsubscribe(this.token); } } </script> <style> .card { /* 从哪里开始排序 */ float: left; /* 这个目的是一行放三个 */ width: 33.333%; padding: .75rem; /* 这个意思是每个div的行距是2分米 */ margin-bottom: 2rem; /* 边框 */ border: 1px solid #efefef; text-align: center; } /* 图片的大小 */ .card > img { margin-bottom: .75rem; /* 控制图片的范围 */ border-radius: 100px; } /* 文本大小 */ .card-text { font-size: 95%; } </style>