您现在的位置是:首页 >其他 >10-Vue技术栈之脚手架配置代理(解决跨域问题)+ GitHub用户搜索案例网站首页其他

10-Vue技术栈之脚手架配置代理(解决跨域问题)+ GitHub用户搜索案例

东方青云、 2024-06-04 10:27:49
简介10-Vue技术栈之脚手架配置代理(解决跨域问题)+ GitHub用户搜索案例

1、基本使用

1.1 方法一

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

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

说明:

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

1.2 方法二

​ 编写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. 缺点:配置略微繁琐,请求资源时必须加前缀。

2、GitHub用户搜索案例

  • 实现效果:

请添加图片描述

源代码已上传至个人主页。

结构目录:
在这里插入图片描述

代码示例:
main文件

import Vue from 'vue'
import App from './App.vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap/dist/js/bootstrap.js'       
Vue.config.productionTip = false
new Vue({
	el: '#app',
	render: h => h(App),
	beforeCreate() {
		Vue.prototype.$bus = this
	}
	// 安装全局事件总线
})

App组件

<template>
  <div class="container">
    <Search/>
    <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组件

<template>
  <nav class="navbar navbar-light bg-light p-4">
    <div class="container-fluid">
      <a class="navbar-brand">Search Github Users</a>
      <form class="d-flex">
        <input
          class="form-control me-2"
          type="search"
          placeholder="Search"
          aria-label="Search"
          v-model="keyWord"
        />
        <button class="btn btn-outline-success" @click.prevent="searchUsers">
          Search
        </button>
      </form>
    </div>
  </nav>
</template>

<script>
import axios from "axios";
export default {
  name: "Search",
  data() {
    return {
      keyWord: "",
    };
  },
  methods: {
    searchUsers() {
      // 请求前的数据
      this.$bus.$emit("updateListData", {
        isFirst: false,
        isLoading: true,
        errmsg: "",
        users: [],
      });
      axios({
        method: "GET",
        url: `https://api.github.com/search/users?q=${this.keyWord}`,
      }).then(
        (response) => {
          console.log(response.data.items);
          // 请求成功后的数据
          this.$bus.$emit("updateListData", {
            isLoading: false,
            errmsg: "",
            users: response.data.items,
          });
        },
        (error) => {
          // 请求错误后的数据
          this.$bus.$emit("updateListData", {
            isLoading: false,
            errmsg: error.message,
            users: [],
          });
        }
      );
    },
  },
};
</script>

<style>
</style>

List组件

<template>
  <div class="row row-cols-1 row-cols-md-1 g-4 mt-3">
    <div class="col">
      <div
        v-show="info.users.length"
        class="card"
        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>
    </div>
    <!-- 欢迎词 -->
    <div v-show="info.isFirst">
      <div class="alert alert-success" role="alert">
        <h4 class="alert-heading">welcome to mo world</h4>
        <p>Click Search at the top</p>
        <hr />
        <p class="mb-0">You'll get the list of users you want</p>
      </div>
    </div>
    <!-- 数据加载中 -->
    <div v-show="info.isLoading" class="text-center">
      <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">Loading...</span>
      </div>
      <div class="spinner-border text-secondary" role="status">
        <span class="visually-hidden">Loading...</span>
      </div>
      <div class="spinner-border text-success" role="status">
        <span class="visually-hidden">Loading...</span>
      </div>
      <div class="spinner-border text-danger" role="status">
        <span class="visually-hidden">Loading...</span>
      </div>
      <div class="spinner-border text-warning" role="status">
        <span class="visually-hidden">Loading...</span>
      </div>
      <div class="spinner-border text-info" role="status">
        <span class="visually-hidden">Loading...</span>
      </div>
      <div class="spinner-border text-light" role="status">
        <span class="visually-hidden">Loading...</span>
      </div>
      <div class="spinner-border text-dark" role="status">
        <span class="visually-hidden">Loading...</span>
      </div>
    </div>
    <!-- 错误 -->
    <div v-show="info.errmsg">{{ info.errmsg }}</div>
  </div>
</template>

<script>
export default {
  name: "List",
  data() {
    return {
      info: {
        isFirst: true,//判断是否为第一次打开页面
        isLoading: false,//判断是否点击了按钮,数据正在在加载中
        errmsg: "",//返回一个错误信息
        users: [],//渲染列表
      },
    };
  },
  mounted() {
    this.$bus.$on("updateListData", (dataObj) => {
      this.info = { ...this.info, ...dataObj };
    });
  },
};
</script>


<style>
.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>
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。