嗨!~ 大家好,我是YK菌 🐷 ,一个微系前端 ✨,爱思考,爱总结,爱记录,爱分享 🏹,欢迎关注我呀 😘 ~ [微信号: yk2012yk2012,微信公众号:ykyk2012]

「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战 (opens new window)

今天我们来用Vue做第三个小demo,一个Github用户搜索的小案例,之前我们用React也做过,这次用Vue做一次,使用axios来发起网络请求。

# 0. 使用Vue-cli配置代理

# 方法①

在vue.config.js中添加如下配置:

devServer:{
  proxy:"http://localhost:5000"
}

说明:

  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

# 方法②

编写vue.config.js配置具体代理规则:

module.exports = {
	devServer: {
      proxy: {
      '/api1': {// 匹配所有以 '/api1'开头的请求路径
        target: 'http://localhost:5000',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api1': ''}
      },
      '/api2': {// 匹配所有以 '/api2'开头的请求路径
        target: 'http://localhost:5001',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}
/*
   changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
   changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
   changeOrigin默认值为true
*/

说明:

  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。

# 1. 准备工作

界面拆分

在这里插入图片描述

# 2. 静态页面

# index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>demo_ajax</title>
    <link rel="stylesheet" href="./static/users_page/bootstrap.css">
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

# App.vue

<template>
  <div class="container">
    <search />
    <users-main />
  </div>
</template>

<script>
import Main from "./components/Main.vue";
import Search from "./components/Search.vue";

export default {
  components: { Search, UsersMain: Main }, //不能用main作为标签名,就换一个名字
};
</script>

<style>
</style>

# 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 {};
</script>

<style>
</style>

# Main.vue

<template>
  <div class="row">
    <div class="card">
      <a href="https://github.com/reactjs" target="_blank">
        <img
          src="https://avatars.githubusercontent.com/u/6412038?v=3"
          style="width: 100px"
        />
      </a>
      <p class="card-text">reactjs</p>
    </div>
    <div class="card">
      <a href="https://github.com/reactjs" target="_blank">
        <img
          src="https://avatars.githubusercontent.com/u/6412038?v=3"
          style="width: 100px"
        />
      </a>
      <p class="card-text">reactjs</p>
    </div>
    <div class="card">
      <a href="https://github.com/reactjs" target="_blank">
        <img
          src="https://avatars.githubusercontent.com/u/6412038?v=3"
          style="width: 100px"
        />
      </a>
      <p class="card-text">reactjs</p>
    </div>
    <div class="card">
      <a href="https://github.com/reactjs" target="_blank">
        <img
          src="https://avatars.githubusercontent.com/u/6412038?v=3"
          style="width: 100px"
        />
      </a>
      <p class="card-text">reactjs</p>
    </div>
    <div class="card">
      <a href="https://github.com/reactjs" target="_blank">
        <img
          src="https://avatars.githubusercontent.com/u/6412038?v=3"
          style="width: 100px"
        />
      </a>
      <p class="card-text">reactjs</p>
    </div>
  </div>
</template>

<script>
export default {};
</script>

<style>
.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>

# 3. 初始化显示

# main.vue

<template>
  <div>
    <h2 v-if="firstView">请输入用户名搜索</h2>
    <h2 v-if="loading">Loading...</h2>
    <h2 v-if="errorMsg">{{errorMsg}}</h2>
    <div class="row">
      <div class="card" v-for="(user, index) in users" :key="index">
        <a :href="user.url" target="_blank">
          <img
            :src="user.avatar_url"
            style="width: 100px"
          />
        </a>
        <p class="card-text">{{user.name}}</p>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 界面有四个状态
      firstView: true,
      loading: false,
      users: null, //[{url:'', avatar_url: '', name: ''}]
      errorMsg: ''
    };
  },
};
</script>

# 4. 交互功能实现

输入关键字点击搜索,界面发生变化

这里我们使用发布订阅的库 pubsub-js

# 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="searchName"
      />
      <button @click="search">Search</button>
    </div>
  </section>
</template>

<script>
import PubSub from "pubsub-js";
export default {
  data() {
    return {
      searchName: "",
    };
  },
  methods: {
    search() {
      const searchName = this.searchName.trim();
      if (searchName) {
        // 发布搜索的消息
        PubSub.publish("search", searchName);
      }
    },
  },
};
</script>

<style>
</style>

# Main.vue

<template>
  <div>
    <h2 v-if="firstView">请输入用户名搜索</h2>
    <h2 v-if="loading">Loading...</h2>
    <h2 v-if="errorMsg">{{ errorMsg }}</h2>
    <div class="row" v-else>
      <div class="card" v-for="(user, index) in users" :key="index">
        <a :href="user.url" target="_blank">
          <img :src="user.avatar_url" style="width: 100px" />
        </a>
        <p class="card-text">{{ user.name }}</p>
      </div>
    </div>
  </div>
</template>

<script>
import PubSub from "pubsub-js";
import axios from "axios";
export default {
  data() {
    return {
      // 界面有四个状态
      firstView: true,
      loading: false,
      users: null, // [{url:'', avatar_url: '', name: ''}]
      errorMsg: "",
    };
  },
  mounted() {
    // 订阅搜索的消息
    PubSub.subscribe("search", (msg, searchName) => {
      // 说明需要发ajax请求搜索
      const url = `https://api.github.com/search/users?q=${searchName}`;

      //更新状态(请求中)
      this.firstView = false;
      this.loading = true;
      this.users = null;
      this.errorMsg = "";

      // 发ajax状态
      axios
        .get(url)
        .then((response) => {
          const result = response.data;
          const users = result.items.map((item) => ({
            url: item.html_url,
            avatar_url: item.avatar_url,
            name: item.login,
          }));
          // 成功, 更新状态(成功)
          this.loading = false;
          this.users = users;
        })
        .catch((error) => {
          // 失败, 更新状态(失败)
          this.loading = false;
          this.errorMsg = "请求失败";
        });
    });
  },
};
</script>

# 5. 效果展示

最后可以看下我们的效果

在这里插入图片描述

最后,欢迎关注我的专栏,和YK菌做好朋友

上次更新: 2022/4/13 12:52:30