前端vue入门(纯代码)17

不管何时何地,永远保持热爱,永远积极向上!!!

19.尚硅谷GitHub案例

1.静态GitHub搜索案例的静态文件:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <!-- 引入第三方样式库bootstrap.css -->
  <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"/>&nbsp;<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>

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。

  • 静态页面展示:并拆分为两个组件【上方:Search.vue组件 + 下方:List.vue组件 】

2.基于代理服务器的GitHub搜索案例

  • 第三方样式库放置的位置如下:

  • 并在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()
      

目前效果的展示以及动图中两个错误的解决办法如下:

  • 错误1: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 */】
  • 错误2:【图片加载报错的点击此处

请求数据解释:

  • total_counter:总的数据量
  • incomplete_results: false【不会把所有的数据给你】
  • items:实际搜索到的数据量

目前代码为:

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 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() {
      // 获取该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">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 {};
</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>
  • 然后,把Search组件拿到的数据怎么在页面展示出来:涉及Search组件【给数据】与List组件【接收数据】之间的通信【兄弟组件之间通信:1.全局数据总线 或 2.消息的订阅与发布】
  • 拿到items这个大数据,里面有30条小数据,每一条数据包含的属性如下:

  • 利用全局事件总线实现组件之间的通信,并且将收到数据在页面展示出来,初步效果如下:
  • 【注意】绑定数据时,一定要动态绑定,一定要加冒号,比如下面代码中的【 :src=“user.avatar_url”】

此时代码为:

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 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() {
      // 获取该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, '', [])
      
      • 缺点1:不优雅不直观,不写注释压根不知道传过去的true、false、’’、[]啥意思;
      • 缺点2:接收方必须按照索引顺序才能正确获取参数。
    • 方式2:传过去的参数封装成json对象方式:

      this.$bus.$emit('updateListData',{isLoading:true,errorMsg:'',users:[]})
      
    • 接收方:接收方式2传过来的数据,然后通过整个对象赋值。

      • 缺点:会丢失属性值,data函数有4个属性,而传递过来的dataObj对象只有3个属性,那么通过整个对象赋值后,最后控制台会整个替换从而丢失一个isFirst属性。
      • 为什么传递过来的dataObj对象只有3个属性:因为isFirst属性在最初页面展示完欢迎词后,就变为false了,后续都不会再变化了,所以,不用再传isFirst属性了。
    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>
    <!-- built files will be auto injected -->
  </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 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,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>
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值