19.尚硅谷GitHub案例
】index.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="stylesheet" href="./bootstrap.css">
<link rel="stylesheet" href="./index.css">
head>
<body>
<div id="app">
<div class="container">
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Usersh3>
<div>
<input type="text" placeholder="enter the name you search"/> <button>Searchbutton>
div>
section>
<div class="row">
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img src="https://cn.vuejs.org/images/logo.svg" style='width: 100px'/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img src="https://cn.vuejs.org/images/logo.svg" style='width: 100px'/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img src="https://cn.vuejs.org/images/logo.svg" style='width: 100px'/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img src="https://cn.vuejs.org/images/logo.svg" style='width: 100px'/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img src="https://cn.vuejs.org/images/logo.svg" style='width: 100px'/>
a>
<p class="card-text">xxxxxxp>
div>
div>
div>
div>
body>
html>
index.css
.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%;
}
bootstrap.css
: 引入第三方样式库bootstrap.css。
并在index.html
文件中引入:
<link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
拆分改写完后,展示:
github接口地址:【https://api.github.com/search/users?q=xxx
】这是github维护的一个简单测试接口,其中xxx为:输入的内容,github接口就会返回xxx相关的数据。
axios的get请求url拼接参数有2种方式:
方式1:字符串+拼接
axios.get('https://api.github.com/search/users?q='+this.keyWord).then()
方式2:采用ES6语法,地址字符串采用反单引号【``】,同时使用**【${}】**【不是单引号,不是单引号!!!】
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then()
目前效果的展示以及动图中两个错误的解决办法如下:
DevTools failed to load source map: Could not load content for http://localhost:8080/css/bootstrap.css.map: HTTP 错误:状态代码 404,net::ERR_HTTP_RESPONSE_CODE_FAILURE
【点击此处】删掉bootstrap.css文件中的最后一行代码:【/*# sourceMappingURL=bootstrap.css.map */】
请求数据解释:
目前代码为:
App.vue
<template>
<div class="container">
<Search/>
<List/>
div>
template>
<script>
import List from './components/List';
import Search from './components/Search';
export default {
components: { List, Search},
name: 'App',
};
script>
Search.vue
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Usersh3>
<div>
<input type="text"
placeholder="enter the name you search"
v-model="keyWord"
/>
<button @click="searchUsers">Searchbutton>
div>
section>
template>
<script>
import axios from 'axios';
export default {
name: 'Search',
data() {
return {
keyWord:'',
}
},
methods: {
searchUsers() {
// 获取该url:github搜索的数据
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
//请求成功后
(response)=>{
console.log(response.data);
},
//请求失败后
(error)=>{
console.log('我请求数据失败了');
},
);
},
},
};
script>
<style>style>
List.vue
<template>
<div class="row">
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://v2.cn.vuejs.org/images/logo.svg "
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://v2.cn.vuejs.org/images/logo.svg "
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://v2.cn.vuejs.org/images/logo.svg "
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://v2.cn.vuejs.org/images/logo.svg "
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://v2.cn.vuejs.org/images/logo.svg "
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
div>
template>
<script>
export default {};
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>
此时代码为:
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中模板未解析,且this是vm
beforeCreate() {
// this:指的是vm
Vue.prototype.$bus = this //安装全局事件总线$bus
}
})
App.vue组件不变
Search.vue
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Usersh3>
<div>
<input type="text"
placeholder="enter the name you search"
v-model="keyWord"
/>
<button @click="searchUsers">Searchbutton>
div>
section>
template>
<script>
import axios from 'axios';
export default {
name: 'Search',
data() {
return {
keyWord:'',
}
},
methods: {
searchUsers() {
// 获取该url:github搜索的数据
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
//请求成功后触发自定义事件,并传递数据
(response)=>{
console.log(this);// this指vc
console.log(response.data);
this.$bus.$emit('updateListData',response.data.items)
},
//请求失败后
(error)=>{
console.log('我请求数据失败了');
this.$bus.$emit('updateListData',response.data.items)
},
);
},
},
};
script>
List.vue
<template>
<div class="row">
<div class="card"
v-show="users.length"
v-for="user in 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>
div>
template>
<script>
export default {
name: 'List',
data() {
return {
users:[],
};
},
// 全局数据总线:
// 接收数据的一方:在mounted钩子中定义自定义事件
mounted() {
// 绑定事件updateListData,并在回调函数中接收来自Search组件的数据【对象的形式:dataObj】
this.$bus.$on('updateListData',(dataObj) => {
this.users=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: 0.75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card > img {
margin-bottom: 0.75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
style>
继续完善页面:
1、数据加载之前,页面展示:欢迎词!!
<h2 v-show="info.isFirst">欢迎使用免费的GitHub接口!h2>
2、数据加载中,页面展示:加载中!!
<h2 v-show="info.isLoading">页面加载中....h2>
3、数据加载错误,页面展示:错误信息!!
<h2 v-show="info.errorMsg">{{ info.errorMsg }}h2>
全局事件总线传多个参数方式有以下几种:
this.$bus.$emit('自定义事件',传递的参数)
方式1:直接传多个参数:
this.$bus.$emit('updateListData', true, false, '', [])
方式2:传过去的参数封装成json对象方式:
this.$bus.$emit('updateListData',{isLoading:true,errorMsg:'',users:[]})
接收方:接收方式2传过来的数据,然后通过整个对象赋值。
data() {
return {
info:{
isFirst:true,
isLoading:false,
errMsg:'',
users:[]
}
}
},
mounted() {
this.$bus.$on('updateListData',(dataObj)=>{
this.info= dataObj;
})
},
通过ES6语法实现局部更新,语法:{…原数据,…接收数据}:dataObj没有的属性用data() 原有的,dataObj包含的属性采用dataObj传递过来的值,另一个好处传递方不按属性顺序传值也能接收。传递方,比如data()中isFirst为第一个属性,而我传递时放在了{}的最后也有效。
// 对象合并:相同的属性以后面的对象为主
this.info = {...this.info,...dataObj}
问题:如下面代码一样,可以把dataObj直接复制给this._data中吗?
data() {
return {
isFirst:true,
isLoading:false,
errMsg:'',
users:[]
}
},
mounted() {
this.$bus.$on('updateListData',(dataObj)=>{
this._data= dataObj;
})
},
- 不能,如果赋值给
this._data
就破坏数据结构了,因为直接赋值方式不会让vue动态代理给_data
中配置get和set
方法,没有响应了。
最终完善后的效果如下:
完整代码:
index.html
DOCTYPE html>
<html lang="zh-en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
<title><%= htmlWebpackPlugin.options.title %>title>
head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.strong>
noscript>
<div id="app">div>
body>
html>
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中模板未解析,且this是vm
beforeCreate() {
// this:指的是vm
Vue.prototype.$bus = this //安装全局事件总线$bus
}
})
App.vue文件
<template>
<div class="container">
<Search/>
<List/>
div>
template>
<script>
import List from './components/List';
import Search from './components/Search';
export default {
components: { List, Search},
name: 'App',
};
script>
Search.vue文件
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Usersh3>
<div>
<input type="text"
placeholder="enter the name you search"
v-model="keyWord"
/>
<button @click="searchUsers">Searchbutton>
div>
section>
template>
<script>
import axios from 'axios';
export default {
name: 'Search',
data() {
return {
keyWord:'',
}
},
methods: {
searchUsers() {
//请求前更新List的数据
this.$bus.$emit('updateListData',{isLoading:true,errorMsg:'',users:[],isFirst:false})
// 获取该url:github搜索的数据
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
//请求成功后触发自定义事件,并传递数据
(response)=>{
console.log(this);// this指vc
console.log(response.data);
this.$bus.$emit('updateListData',{isLoading:false,errorMsg:'',users:response.data.items})
},
//请求失败后
(error)=>{
console.log('我请求数据失败后,传递失败的信息,并将users数据初始化');
// 请求失败后 users必须制空,不然页面还是会显示上次成功请求的数据
this.$bus.$emit('updateListData',{isLoading:false,errorMsg:error.message,users:[]})
},
);
},
},
};
script>
List.vue文件
<template>
<div class="row">
<div
class="card"
v-show="info.users.length"
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>
<h2 v-show="info.isFirst">欢迎使用免费的GitHub接口!h2>
<h2 v-show="info.isLoading">页面加载中....h2>
<h2 v-show="info.errorMsg">{{ info.errorMsg }}h2>
div>
template>
<script>
export default {
name: 'List',
data() {
return {
info: {
isFirst: true,
isLoading: false,
errorMsg: '',
users: [],
},
};
},
// 全局数据总线:
// 接收数据的一方:在mounted钩子中定义自定义事件
mounted() {
// 绑定事件updateListData,并在回调函数中接收来自Search组件的数据【对象的形式:dataObj】
this.$bus.$on('updateListData', (dataObj) => {
// 对象合并:相同的属性以后面的对象为主
this.info = {...this.info,...dataObj}
});
},
};
script>
<style scoped>
h2 {
margin-left: 50px;
}
.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: 0.75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card > img {
margin-bottom: 0.75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
style>