• 《进阶篇第7章》学习vue中的ajax之后,练习vue案例-github用户搜索案例


    在这里插入图片描述

    概述:该案例是学习完第6章:vue中的ajax之后,进行的练习和总结,相关知识点详情内容,请查看我的上一篇同一专栏文章。

    7.1github接口地址

    https://api.github.com/search/users?q=xxx
    这是github维护的一个简单测试接口,其中xxx输入什么内容,github接口就会返回相关的数据。

    7.2案例代码

    注意点1:

    问题:这次如何划分组件?

    在这里插入图片描述
    答案:这次只划分2个组件,上方的search.vue,下方的List.vue

    注意点2:axios的get请求url拼接参数有2种方式

    方式1:字符串+拼接

    axios.get(`https://api.github.com/search/users?q=` + this.keyWord).then()
    
    • 1

    方式2:采用ES6语法,地址字符串采用单引号’’,同时使用${}

    axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then()
    
    • 1

    注意点3:优化页面效果,初始化显示展示欢迎词,点击按钮调接口时显示加载中…,如果调用报错显示错误信息提示,因此定义4个属性来控制:isFirst、isLoading、errMsg、users,
    初始化时:isFirst:true, isLoading:false, errMsg:‘’, users:[]
    请求前更新List的数据:isFirst:false, isLoading:true, errMsg:‘’, users:[]
    请求成功后更新List的数据:isLoading:false, errMsg:‘’, users:response.data.items
    请求失败后更新List的数据:isLoading:false, errMsg:error.message, users:[]
    请求失败后 users必须制空,不然页面还是会显示上次成功请求的数据

    注意点4:
    全局事件总线传多个参数方式有以下几种
    方式1:如下直接传多个参数,缺点1:不优雅不直观,不写注释压根不知道传过去的true、false、’’、[]啥意思;缺点2:接收方必须按照索引顺序才能获取参数。

    this.$bus.$emit('updateListData', true, false, '', [])
    
    • 1

    方式2:传过去的参数封装成json对象方式,
    传递方

    this.$bus.$emit('updateListData',{isLoading:true,errMsg:'',users:[],isFirst:false})
    
    • 1

    接收方,方式1通过this.属性挨个赋值,缺点:我有100个属性赋值100行?不现实

    data() {
    	return {
    		info:{
    			isFirst:true,
    			isLoading:false,
    			errMsg:'',
    			users:[]
    		}
    	}
    },
    mounted() {
    	this.$bus.$on('updateListData',(dataObj)=>{
                 this.info.isFirst = dataObj.isFirst;
                 this.info.isLoading = dataObj.isLoading;
                 this.info.errMsg = dataObj.errMsg;
                 this.info.users = dataObj.users;
    	})
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    接收方,方式2通过整个对象赋值,缺点:会丢属性值,data函数有4个属性,而我传递的dataObj只有3个属性,那么最后控制台会整个替换从而丢一个属性

    data() {
    	return {
    		info:{
    			isFirst:true,
    			isLoading:false,
    			errMsg:'',
    			users:[]
    		}
    	}
    },
    mounted() {
    	this.$bus.$on('updateListData',(dataObj)=>{
                  this.info= dataObj;          
    	})
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    接收方,方式3通过ES6语法实现局部更新,语法:{…原数据,…接收数据},dataObj没有的属性用data() 原有的,dataObj包含的属性采用dataObj传递过来的值,另一个好处传递方不按属性顺序传值也能接收。
    传递方,比如data()中isFirst为第一个属性,而我传递时放在了{}的最后也有效

    this.$bus.$emit('updateListData',{isLoading:true,errMsg:'',users:[],isFirst:false})
    
    • 1

    接收方

    data() {
    	return {
    		info:{
    			isFirst:true,
    			isLoading:false,
    			errMsg:'',
    			users:[]
    		}
    	}
    },
    mounted() {
    	this.$bus.$on('updateListData',(dataObj)=>{
                 this.info = {...this.info,...dataObj}       
    	})
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    注意点5:

    问题:注意点3中接收方,方式2通过整个对象赋值方式,我可以把dataObj直接复制给this._data中吗?

    答案:不能,如果赋值给this._data就破坏数据结构了,因为直接赋值方式不会让vue动态代理给_data中设置get和set方法。

    完整代码

    项目结构

    在这里插入图片描述

    main.js

    //引入Vue
    import Vue from 'vue'
    //引入App
    import App from './App.vue'
    //关闭Vue的生产提示
    Vue.config.productionTip = false
    
    //创建vm
    new Vue({
    	el:'#app',
    	render: h => h(App),
    	beforeCreate() {
    		Vue.prototype.$bus = this
    	},
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    App.vue

    <template>
    	<div class="container">
    		<Search/>
    		<List/>
    	</div>
    </template>
    
    <script>
    	import Search from './components/Search'
    	import List from './components/List'
    	export default {
    		name:'App',
    		components:{Search,List}
    	}
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Search.vue

    <template>
    	<section class="jumbotron">
    		<h3 class="jumbotron-heading">Search Github Users</h3>
    		<div>
    			<input type="text" placeholder="enter the name you search" v-model="keyWord"/>&nbsp;
    			<button @click="searchUsers">Search</button>
    		</div>
    	</section>
    </template>
    
    <script>
    	import axios from 'axios'
    	export default {
    		name:'Search',
    		data() {
    			return {
    				keyWord:''
    			}
    		},
    		methods: {
    			searchUsers(){
    				//请求前更新List的数据
    				this.$bus.$emit('updateListData',{isLoading:true,errMsg:'',users:[],isFirst:false})
            //axios的get请求url拼接参数方式1:字符串+拼接
    				axios.get(`https://api.github.com/search/users?q=` + this.keyWord).then(
    				//axios的get请求url拼接参数方式2:采用ES6语法,地址字符串采用单引号’’,同时使用${}
            // axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
    					response => {
    						console.log('请求成功了')
    						//请求成功后更新List的数据
    						this.$bus.$emit('updateListData',{isLoading:false,errMsg:'',users:response.data.items})
    					},
    					error => {
    						//请求失败后更新List的数据
    						this.$bus.$emit('updateListData',{isLoading:false,errMsg:error.message,users:[]})
    					}
    				)
    			}
    		},
    	}
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    List.vue

    <template>
    	<div class="row">
    		<!-- 展示用户列表 -->
    		<div v-show="info.users.length" class="card" v-for="user in info.users" :key="user.login">
    			<a :href="user.html_url" target="_blank">
    				<img :src="user.avatar_url" style='width: 100px'/>
    			</a>
    			<p class="card-text">{{user.login}}</p>
    		</div>
    		<!-- 展示欢迎词 -->
    		<h1 v-show="info.isFirst">欢迎使用!</h1>
    		<!-- 展示加载中 -->
    		<h1 v-show="info.isLoading">加载中....</h1>
    		<!-- 展示错误信息 -->
    		<h1 v-show="info.errMsg">{{info.errMsg}}</h1>
    	</div>
    </template>
    
    <script>
    	export default {
    		name:'List',
    		data() {
    			return {
    				info:{
    					isFirst:true,
    					isLoading:false,
    					errMsg:'',
    					users:[]
    				}
    			}
    		},
    		mounted() {
    			this.$bus.$on('updateListData',(dataObj)=>{
            //接收方,方式1通过this.属性挨个赋值,缺点:我有100个属性赋值100行?
            // this.info.isFirst = dataObj.isFirst;
            // this.info.isLoading = dataObj.isLoading;
            // this.info.errMsg = dataObj.errMsg;
            // this.info.users = dataObj.users;
    
            //接收方,方式2通过整个对象赋值,缺点:会丢属性值
            // this.info = dataObj;
    
            //接收方,方式3采用ES6语法,局部更新
    				this.info = {...this.info,...dataObj}
    			})
    		},
    	}
    </script>
    
    <style scoped>
    	.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;
    		margin-bottom: 2rem;
    		border: 1px solid #efefef;
    		text-align: center;
    	}
    
    	.card > img {
    		margin-bottom: .75rem;
    		border-radius: 100px;
    	}
    
    	.card-text {
    		font-size: 85%;
    	}
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    结果展示:

    在这里插入图片描述

    7.3把github用户搜索案例使用axios方式改为使用vue-resource方式

    改变地方

    main.js

    //引入插件
    import vueResource from 'vue-resource'
    //使用插件
    Vue.use(vueResource)
    
    • 1
    • 2
    • 3
    • 4

    Search.vue

    旧代码:
    axios.get(`https://api.github.com/search/users?q=` + this.keyWord).then()
    新代码:
    this.$http.get(`https://api.github.com/search/users?q=${this.keyWord}`).then()
    
    • 1
    • 2
    • 3
    • 4

    完整代码

    main.js

    //引入Vue
    import Vue from 'vue'
    //引入App
    import App from './App.vue'
    //关闭Vue的生产提示
    Vue.config.productionTip = false
    //引入插件
    import vueResource from 'vue-resource'
    //使用插件
    Vue.use(vueResource)
    
    //创建vm
    new Vue({
    	el:'#app',
    	render: h => h(App),
    	beforeCreate() {
    		Vue.prototype.$bus = this
    	},
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    App.vue

    <template>
    	<div class="container">
    		<Search/>
    		<List/>
    	</div>
    </template>
    
    <script>
    	import Search from './components/Search'
    	import List from './components/List'
    	export default {
    		name:'App',
    		components:{Search,List}
    	}
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Search.vue

    <template>
    	<section class="jumbotron">
    		<h3 class="jumbotron-heading">Search Github Users</h3>
    		<div>
    			<input type="text" placeholder="enter the name you search" v-model="keyWord"/>&nbsp;
    			<button @click="searchUsers">Search</button>
    		</div>
    	</section>
    </template>
    
    <script>
    	//import axios from 'axios'
    	export default {
    		name:'Search',
    		data() {
    			return {
    				keyWord:''
    			}
    		},
    		methods: {
    			searchUsers(){
    				//请求前更新List的数据
    				this.$bus.$emit('updateListData',{isLoading:true,errMsg:'',users:[],isFirst:false})
            this.$http.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
            //axios的get请求url拼接参数方式1:字符串+拼接
    				//axios.get(`https://api.github.com/search/users?q=` + this.keyWord).then(
    				//axios的get请求url拼接参数方式2:采用ES6语法,地址字符串采用单引号’’,同时使用${}
            // axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
    					response => {
    						console.log('请求成功了')
    						//请求成功后更新List的数据
    						this.$bus.$emit('updateListData',{isLoading:false,errMsg:'',users:response.data.items})
    					},
    					error => {
    						//请求失败后更新List的数据
    						this.$bus.$emit('updateListData',{isLoading:false,errMsg:error.message,users:[]})
    					}
    				)
    			}
    		},
    	}
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    List.vue

    <template>
    	<div class="row">
    		<!-- 展示用户列表 -->
    		<div v-show="info.users.length" class="card" v-for="user in info.users" :key="user.login">
    			<a :href="user.html_url" target="_blank">
    				<img :src="user.avatar_url" style='width: 100px'/>
    			</a>
    			<p class="card-text">{{user.login}}</p>
    		</div>
    		<!-- 展示欢迎词 -->
    		<h1 v-show="info.isFirst">欢迎使用!</h1>
    		<!-- 展示加载中 -->
    		<h1 v-show="info.isLoading">加载中....</h1>
    		<!-- 展示错误信息 -->
    		<h1 v-show="info.errMsg">{{info.errMsg}}</h1>
    	</div>
    </template>
    
    <script>
    	export default {
    		name:'List',
    		data() {
    			return {
    				info:{
    					isFirst:true,
    					isLoading:false,
    					errMsg:'',
    					users:[]
    				}
    			}
    		},
    		mounted() {
    			this.$bus.$on('updateListData',(dataObj)=>{
            //接收方,方式1通过this.属性挨个赋值,缺点:我有100个属性赋值100行?
            // this.info.isFirst = dataObj.isFirst;
            // this.info.isLoading = dataObj.isLoading;
            // this.info.errMsg = dataObj.errMsg;
            // this.info.users = dataObj.users;
    
            //接收方,方式2通过整个对象赋值,缺点:会丢属性值
            // this.info = dataObj;
    
            //接收方,方式3采用ES6语法,局部更新
    				this.info = {...this.info,...dataObj}
    			})
    		},
    	}
    </script>
    
    <style scoped>
    	.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;
    		margin-bottom: 2rem;
    		border: 1px solid #efefef;
    		text-align: center;
    	}
    
    	.card > img {
    		margin-bottom: .75rem;
    		border-radius: 100px;
    	}
    
    	.card-text {
    		font-size: 85%;
    	}
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
  • 相关阅读:
    PE结构学习(3)_RVA转换成FOA
    docker系列(4) - docker镜像制作
    R语言动量交易策略分析调整后的数据
    金融量化项目案例 -- 双均线策略制定
    使用opencv结合帧差法和背景减法 检测场景异常情况
    go return返回值屏蔽
    易捷行云EasyStack创始人兼CEO陈喜伦:坚持开源生态产品化 与社区和客户齐创新共成长
    数据集的整理和命名和格式转换
    实验笔记之——Gaussian Splatting SLAM配置与测试
    我国首个桌面操作系统开发者平台 openKylin 正式发布
  • 原文地址:https://blog.csdn.net/a924382407/article/details/125482689