文章目录
项目介绍:
用户输入关键词,拿到关键词后向github发送ajax请求。拿到返回的数据后对其进行渲染。
效果展示:
- 由于用户名是
<h2/>
标签,所以会比较大,撑大了父元素让整个布局显得有点乱 - 不过写完才发现,就懒得优化了
一、创建并配置好vue脚手架
1,创建Vue脚手架,选择Vue2的默认版本
2,vscode打开我们创建的脚手架
准备工作:
- 删除
components
文件夹中的文件 - 删除App.vue中的内容并且重新配置模板
- 关闭eslint语法检查(不关闭会报错)
- 在
vue.config.js
文件中新增配置项lintOnSave:false
二、创建组件并完成静态页面
组件结构很简单,Header
组件用来搜索,Main
组件用来展示
接着开始写静态页面
Header组件
<template lang="">
<div>
<div class="search">
<input type="text">
<button>点我搜索</button>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.search{
display: flex;
justify-content: center;
}
</style>
Main组件
<template lang="">
<div>
<div class="show_container">
<div class="card">
<a href="">
<img src="../assets/download.jpg" alt="">
</a>
<h2>UserName</h2>
</div>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.show_container{
margin-top: 50px;
width: 90vw;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
img{
width: 100px;
height: 100px;
object-fit: cover;
}
h2{
text-align: center;
}
</style>
App组件
- 引入、注册并使用Header和Main两个组件
<template lang="">
<div class="main_container">
<Header></Header>
<Main></Main>
</div>
</template>
<script>
import Header from './components/Header.vue'
import Main from './components/Main.vue'
export default {
components: {
Header,
Main
}
}
</script>
<style scoped>
.main_container {
display: flex;
flex-direction: column;
align-items: center;
}
* {
margin: 0;
padding: 0;
}
</style>
- 输入
yarn serve
执行项目
静态页面效果如下
三、使用axios发送ajax请求
首先要弄懂啥是静态页面,啥是动态页面,千万别以为页面上有个动图就是动态页面了;通俗点来讲,静态页面没有交互效果,上面的都是死数据;而动态页面用户可以很好的进行交互,可以根据自己的想法得到想要的数据。
先别急着来请求数据,我们向github请求数据总得带关键词吧,而关键词也就是我们Header组件中用户输入的内容,那么开干吧!
- 首先给
<input/>
输入框进行双向数据绑定:v-model=‘keyWord’
- 接着给
<input/>
绑定回车事件,给button绑定点击事件,并指向同一函数searchUsers
以下为Header组件
<template lang="">
<div>
<div class="search">
<input type="text" v-model="keyWord" @keyup.enter="searchUsers">
<button @click="searchUsers">点我搜索</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
keyWord: ''
}
},
methods: {
searchUsers() {
}
},
}
</script>
<style scoped>
.search {
display: flex;
justify-content: center;
}
</style>
- 接下来就是要根据获取到的
keyWord
发送ajax
请求了,那么在哪个组件中发呢?必然是Main组件,因为请求回来的数据将在Main组件中渲染。 - 这时候我们将要想办法将Header中的数据
keyWord
传给其兄弟组件Main。有N中办法,我选择的是全局事件总线(我会单独写一篇关于它的)
- 首先在
main.js
中定义全局事件总线
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
beforeCreate(){
//将vm挂载在到Vue的显式原型上
Vue.prototype.$bus = this
}
}).$mount('#app')
- 在Main组件中自定义事件并指定回调
mounted() {
//定义事件,指定回调函数searchAjax
this.$bus.$on('key',this.searchAjax)
},
methods:{
//q是Header组件传过来的keyWord
searchAjax(q){
}
}
- 在Header组件中触发自定义事件并传送自己的参数
methods: {
searchUsers() {
//将数据传给Main组件
this.$bus.$emit('key',this.keyWord)
}
},
- 这时候在Main组件中已经可以拿到Header组件中的keyWord了
开始玩axios
,我们的api是https://api.github.com/search/users
(querry参数)
- 安装
axios
;命令:yarn add axios -S
- 在Main组件中引入
axios
;命令:import axios from 'axios'
- 根据拿到的
keyWord
作为querry参数发送请求
searchAjax(q){
axios({
url:'https://api.github.com/search/users',
method:'get',
params:{
// q:q可简写为下
q
}
}).then(response => {
console.log(response);
}).catch(error => {
console.log(error.message);
})
}
- 测试并观察返回的数据结构:随便输入关键词回车,观察控制台中返回的数据结构,发现data下的
items
数组是我们所需要的
- 我们先准备一个容器数组
users
用来存放筛选后的items
数组
data() {
return {
users:[]
}
},
- 接着用
map()
方法加工items
数组并将加工结果传给users
.then(response => {
this.users = response.data.items.map(item => ({
id: item.id,
userName: item.login,
avatar: item.avatar_url,
page: item.html_url,
}))
})
- 最后一步,渲染数据,在Main组件中
<template lang="">
<div>
<div class="show_container">
<div class="card" v-for="(user, index) in users" :key="user.id">
<a :href="user.page">
<img :src="user.avatar" alt="">
</a>
<h2>{{user.userName}}</h2>
</div>
</div>
</div>
</template>
完成!你学废了吗?
效果如下
你以为这就完了吗?NONONO,优化在后面。。。
四、优化实现人性化效果
1、优化一:首先用户这个东西是很可怕的哇,要考虑用户什么也不输入就回车的情况
优化后的Header组件如下
<template lang="">
<div>
<div class="search">
<input type="text" v-model="keyWord" @keyup.enter="searchUsers">
<button @click="searchUsers">点我搜索</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
keyWord: ''
}
},
methods: {
searchUsers() {
//在这儿判断以下用户是否啥也没输就开始搜索了
if (this.keyWord.trim()) {
//将数据传给Main组件
this.$bus.$emit('key', this.keyWord)
}else{
//如果啥也没输弹出警告
alert('别给老子输空串儿!')
}
}
},
}
</script>
<style scoped>
.search {
display: flex;
justify-content: center;
}
</style>
优化后效果如下
2、优化二:在Main组件中,当没有数据的时候页面一片空白,非常的不美观;
- 当开始搜索时,数据返回有一段时间,得让用户知道已经开始搜了,只是还没传过来(别骂了,是你网速的问题)
- 如果搜索失败,给个报错页面,提示下报错信息就完了(甩锅王)
开干!
优化后的Main组件如下
<template lang="">
<div>
<div class="show_container">
<!-- 用条件语句决定显示哪一个标签 -->
<h2 v-if="isFirst">尊贵的天龙人,请输入用户名查找</h2>
<h2 v-else-if="isBegin">查找中,别急,快了</h2>
<div v-else-if="isError">
<h2>不好意思,出了点问题</h2>
<h2>{{error}}</h2>
</div>
<div v-else class="card" v-for="(user, index) in users" :key="user.id">
<a :href="user.page">
<img :src="user.avatar" alt="">
</a>
<h2>{{user.userName}}</h2>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
users: [],
error:'',
// 三个数据驱动四种状态,分别是一开始,搜索中,出错,正常显示
isFirst:true,
isBegin:false,
isError:false
}
},
mounted() {
//定义事件,指定回调函数searchAjax
this.$bus.$on('key', this.searchAjax)
},
methods: {
searchAjax(q) {
// 开始搜索,将第一次置为false,将开始搜索置为true
this.isFirst = false
this.isBegin = true
axios({
url: 'https://api.github.com/search/users',
method: 'get',
params: {
// q:q可简写为下
q
}
}).then(response => {
// 数据回来了,将开始搜索置为false便于下一步显示数据
this.isBegin = false
this.users = response.data.items.map(item => ({
id: item.id,
userName: item.login,
avatar: item.avatar_url,
page: item.html_url,
}))
}).catch(error => {
// 出错,首先将isBegin置为false
// 然后将isError置为true,显示错误信息
this.isBegin = false
this.isError = true
this.error = error.message
})
}
}
}
</script>
<style scoped>
.show_container {
margin-top: 50px;
width: 90vw;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
img {
width: 100px;
height: 100px;
object-fit: cover;
}
h2 {
text-align: center;
}
</style>
优化后效果如下
-
以下是请求成功的情况
-
以下是请求失败的情况
总结
- 小孩子才写总结
- 昨天刚成年