前言
系列文章目录:
[Vue]目录
老师的课件笔记,不含视频 https://www.aliyundrive.com/s/B8sDe5u56BU
1. 案例效果
2. 静态页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<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 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/xxxxxx" target="_blank">
<img src="https://cn.vuejs.org/images/logo.svg" style='width: 100px'/>
</a>
<p class="card-text">xxxxxx</p>
</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">xxxxxx</p>
</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">xxxxxx</p>
</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">xxxxxx</p>
</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">xxxxxx</p>
</div>
</div>
</div>
</div>
</body>
</html>
.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%;
}
3. 组件的拆分
3.1 目录结构
3.2 引入第三方css样式
在index.html中使用link标签引入第三方css样式
由于import导入第三方样式,会对引入的样式进行代码检查,而在代码中使用了本地没有的字体样式,会报错;使用link标签引入第三方样式不会进行严格的代码检查,不会报错。
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<!-- 针对ie浏览器的一个特殊配置,让ie浏览器以最高的渲染级别渲染页面 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 开启移动端的理想视口 -->
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- 配置页签图标 <%= BASE_URL %> 表示public文件夹所在的路径,防止项目部署后出现路径的错误-->
<!-- 所以在该html文件中路径不使用 ./ ../ -->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- 引入第三方css样式 bootstrap -->
<link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
<!-- 网页的标题 -->
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<!-- 浏览器不支持js,页面会显示noscript标签中的内容;支持js则不渲染noscript标签中的内容 -->
<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>
<!-- built files will be auto injected -->
</body>
</html>
3.3 拆分组件
App.vue
<template>
<div class="container">
<!-- 使用子组件 -->
<Search></Search>
<List></List>
</div>
</template>
<script>
// 导入子组件
import Search from './components/Search.vue'
import List from './components/List.vue'
export default {
name: 'App',
// 注册子组件
components: {
Search,
List
}
}
</script>
Search.vue
<template>
<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>
</template>
<script>
export default {
name: 'Search'
}
</script>
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">xxxxxx</p>
</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">xxxxxx</p>
</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">xxxxxx</p>
</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">xxxxxx</p>
</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">xxxxxx</p>
</div>
</div>
</template>
<script>
export default {
name: 'List'
}
</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>
4. 列表展示实现
4.1 查询请求数据
请求接口地址:
https://api.github.com/search/users?q=xxx
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"
/>
<button @click="searchUsers">Search</button>
</div>
</section>
</template>
<script>
// 导入axios
import axios from 'axios'
export default {
name: 'Search',
data() {
return {
keyWord: ''
}
},
methods: {
searchUsers() {
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
response=>{
console.log('请求成功', response.data)
},
error=>{
console.log('请求失败', error)
}
)
}
},
}
</script>
4.2 数据传递
子组件Search与List为兄弟组件,这里使用全局事件总线进行数据的传递。
4.2.1 安装全局事件总线
main.js
import Vue from 'vue'
import App from './App.vue'
//关闭vue的生产提示
Vue.config.productionTip = false
new Vue({
render: h => h(App),
beforeCreate() {
// 让vue的实例对象作为全局事件总线
Vue.prototype.$bus = this
}
}).$mount('#app')
4.2.2 全局事件总线绑定自定义事件
List.vue
<script>
export default {
name: 'List',
data() {
return {
users: []
}
},
mounted() {
this.$bus.$on('getUsers', (users)=>{
console.log('List组件收到了数据')
this.users = users
})
}
}
</script>
4.2.3 触发全局事件总线事件
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"
/>
<button @click="searchUsers">Search</button>
</div>
</section>
</template>
<script>
// 导入axios
import axios from 'axios'
export default {
name: 'Search',
data() {
return {
keyWord: ''
}
},
methods: {
searchUsers() {
// 发起请求获取用户数据
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
response=>{
console.log('请求成功')
// 触发全局事件总线事件 传递数据
this.$bus.$emit('getUsers', response.data.items)
},
error=>{
console.log('请求失败', error)
}
)
}
},
}
</script>
4.3 列表数据展示
4.3.1 需要使用的数据
4.3.2 数据展示
List.vue
<template>
<div class="row">
<div class="card" v-for="user in users" :key="user.id">
<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() {
// 全局事件总线绑定事件
this.$bus.$on('getUsers', (users)=>{
console.log('List组件收到了数据')
this.users = users
})
}
}
</script>
5. 完善案例
实现初始页面的欢迎词展示、数据请求过程中的加载提示、请求失败的错误信息显示。
List.vue
<template>
<div class="row">
<!-- 用户列表 -->
<div
class="card"
v-show="info.users"
v-for="user in info.users"
:key="user.id">
<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">welcome to use</h1>
<!-- 加载中 -->
<h1 v-show="info.isLoading">loading...</h1>
<!-- 错误信息 -->
<h1 v-show="info.errorMsg">{{info.errorMsg}}</h1>
</div>
</template>
<script>
export default {
name: 'List',
data() {
return {
info: {
// 是否第一次加载页面
isFirst: true,
// 是否加载数据
isLoading: false,
// 错误信息
errorMsg: '',
// 用户信息
users: []
}
}
},
mounted() {
// 全局事件总线绑定事件
// this.$bus.$on('getUsers', (dataObj)=>{
this.$bus.$on('updateUsers', (dataObj)=>{
console.log('List组件收到了数据')
// this.users = users
// dataObj中有的属性会覆盖this.info中相同的属性
// 没有则this.info保持原值
this.info = {...this.info, ...dataObj}
})
}
}
</script>
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" />
<button @click="searchUsers">Search</button>
</div>
</section>
</template>
<script>
// 导入axios
import axios from 'axios'
export default {
name: 'Search',
data() {
return {
keyWord: ''
}
},
methods: {
searchUsers() {
// 请求开始前初始化数据
this.$bus.$emit('updateUsers', {
// 进行请求了,取消欢迎词
isFirst: false,
// 请求开始,进入加载状态
isLoading: true,
// 无报错信息
errorMsg: '',
// 请求开始前,用户数据为空
users: []
})
// 发起请求获取用户数据
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
response => {
console.log('请求成功')
// 触发全局事件总线事件 传递数据
// this.$bus.$emit('updateUsers', response.data.items)
// 请求成功传递数据
this.$bus.$emit('updateUsers', {
// 原先是否第一次加载页面状态已经修改不用再次传递修改
// 请求结束
isLoading: false,
// 无报错信息
errorMsg: '',
// 用户数据
users: response.data.items
})
},
error => {
console.log('请求失败', error)
// 请求失败传递数据
this.$bus.$emit('updateUsers', {
// 原先是否第一次加载页面状态已经修改不用再次传递修改
// 请求结束
isLoading: false,
// 报错信息
errorMsg: error,
// 请求失败用户数据为空
users: []
})
}
)
}
}
}
</script>