Vue中的Ajax

Posted 库里不会投三分

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue中的Ajax相关的知识,希望对你有一定的参考价值。

文章目录


本案例需要下载axios库: npm install axios

Vue脚手架配置代理

为什么要配置代理服务器

什么是跨域?

跨域资源共享(英语:Cross-origin resource sharing,缩写:CORS),用于让网页的受限资源能够被其他域名的页面访问的一种机制。 --摘自维基百科
跨域的基本三要素:

  • 同域名
  • 同端口
  • 同协议

通俗理解:
我们从站点A对其他站点进行网络请求时,浏览器端和服务端需要对这个请求进行处理,保证这个请求是安全的。 这个处理就是跨域

为什么需要跨域

跨域是为了保证请求的安全作出的策略。

  • 浏览器请求必须遵循同源策略: 同一域名、同一端口、同一协议

跨域方案

  • JSONP跨域
  • CORS跨域
  • 代理跨域

代理跨域

我们的客户端想访问A服务器,但是A服务器存在跨域问题,我们就再开一个同源的代理服务器B,我们把请求给B服务,然后B服务器去访问A服务器,A处理好信息返回给B,B再将数据返回给客户端

跨域问题是前端存在的问题,而我们服务器之间传递信息直接是用http,是不存在什么跨域问题的

接口代理跨域特点

  • 服务端、客户端均不需要配置
  • 通过中间服务器(代理服务器)的配置实现(如nginx、IIS、Apache)
  • 我们这里使用的Vue-CLI也能帮我们实现跨域处理

CORS跨域

  • CORS跨域个人是最常用的(多亏.NET Core对跨域策略的支持非常好用)。
  • CORS跨域是由服务端应用设置的一个跨域策略,比如开放指定的HTTP Method、指定请求方Url、指定请求携带的Headers必须包含的字段等等~。
  • CORS这种方式简单高效,合理的使用它的策略可以保证服务器的安全的同时也提升了前后端的开发体验~;

CORS跨域特点

  • 后端配置,前端直接请求;
  • 策略丰富,可支持多种策略,如HTTP方法、URL等;
  • 前后端交互方式非常规范;
  • 除了常用的GET、POST、HEAD 其他方法进行请求则需要发起OPTIONS请求对服务器端进行跨域允许的许可请求

利用Vue-CLI配置代理服务器

App.vue

<template>
    <div id="root">
        <button @click="getStudents">获取学生信息</button><br/>
        <button @click="getCars">获取汽车信息</button>
    </div>
</template>

<script>
    import axios from 'axios'
    
    export default 
        name:'App',
        methods: 
			getStudents()
				axios.get('http://localhost:8080/lscStudent/students').then(
					response => 
						console.log('请求成功了',response.data)
					,
					error => 
						console.log('请求失败了',error.message)
					
				)
			,
            getCars()
				axios.get('http://localhost:8080/lscCar/cars').then(
					response => 
						console.log('请求成功了',response.data)
					,
					error => 
						console.log('请求失败了',error.message)
					
				)
			
        
    
</script>

vue.config.js:

module.exports = 
  pages: 
      index: 
          entry: 'src/main.js',
      ,
  ,
  lintOnSave:false,
  // 开启代理服务器(方式一)
  // devServer: 
  //     proxy:'http://localhost:5000'
  // 

  //开启代理服务器(方式二)
devServer: 
      proxy: 
          '/lscStudent': 
              target: 'http://localhost:5000',
              pathRewrite:'^/lscStudent':'',
              // ws: true, //用于支持websocket,默认值为true
              // changeOrigin: true //用于控制请求头中的host值,默认值为true
          ,
          '/lscCar': 
              target: 'http://localhost:5001',
              pathRewrite:'^/lscCar':'',
              // ws: true, //用于支持websocket,默认值为true
              // changeOrigin: true //用于控制请求头中的host值,默认值为true
          
      
  

总结

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

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

  • 优点:配置简单,请求资源时直接发给前端即可

  • 缺点:不能配置多个代理,不能灵活的控制请求是否走代理

    • 如果我们请求的数据再8080中存在,那么就直接用代理服务器的,不能访问目标服务器

    • 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

方法二:

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


说明:

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

GitHub用户搜索案例

public/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">
        <!-- 配置页签图标 -->
        <link rel="icon" href="<%= BASE_URL %>favicon.ico">
        <!-- 引入bootstrap样式 -->
        <link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
        <!-- 配置网页标题 -->
        <title><%= htmlWebpackPlugin.options.title %></title>
    </head>
    <body>
        <!-- 容器 -->
        <div id="app"></div>
    </body>
</html>

  • 在这引入bootstrap样式,如果对应的一些样式没有,不会报错,比如字体什么的,如果在main.js中引入,会进行严格的检查,因为是ES6语法

main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue(
    el:"#app",
    render: h => h(App),
    beforeCreate()
        Vue.prototype.$bus = this
    
)

App.vue

<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.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="getUsers">Search</button>
		</div>
    </section>
</template>

<script>
    import axios from 'axios'
    export default 
        name:'Search',
        data() 
            return 
                keyWord:''
            
        ,
        methods: 
            getUsers()
                //请求前更新List的数据
				this.$bus.$emit('updateListData',isLoading:true,errMsg:'',users:[],isFirst:false)
				axios.get(`https://api.github.com/search/users?q=$this.keyWord`).then(
					response => 
						console.log('请求成功了')
						//请求成功后更新List的数据
						this.$bus.$emit('updateListData',isLoading:false,errMsg:'',users:response.data.items)
					,
					error => 
						//请求后更新List的数据
						this.$bus.$emit('updateListData',isLoading:false,errMsg: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.id">
            <a :href="user.html_url" target="_blank">
                <img :src="user.avatar_url" style='width: 100px'/>
            </a>
            <h4 class="card-title">user.login</h4>
        </div>
        <!-- 展示欢迎词 -->
        <h1 v-show="info.isFirst">欢迎使用!</h1>
        <!-- 展示加载中 -->
        <h1 v-show="info.isLoading">加载中...</h1>
        <!-- 展示错误信息 -->
        <h1 v-show="info.errMsg">errMsg</h1>
    </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
            )
        ,
        beforeDestroy()
            this.$bus.$off('updateListData')
        
    
</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>

总结:

vue项目常用的两个Ajax库:

  1. axios:通用的Ajax请求库,官方推荐,效率高
  2. vue-resource:vue插件库,vue 1.x使用广泛,官方已不维护

通过 VUE.js 中的 ajax 调用读取 JSON

【中文标题】通过 VUE.js 中的 ajax 调用读取 JSON【英文标题】:JSON reading through an ajax call in VUE.js 【发布时间】:2019-05-14 10:32:28 【问题描述】:

我的本​​地 vue“服务器”中有一个 json,与应用程序所在的文件夹相同。 我想使用 promise 进行 ajax 调用,但我不确定如何将它连接到我的代码。 这是我的代码:

export default 
  name: "app",
  data() 
    return 
      items: []
    ;
  ,

  created: function() 
    this.fetchData();
  ,

  methods: 
    fetchData: function() 
      var self = this;
      $.get("books.json", function(data) 
        self.items = data;
      );
    
  
;

function makeAjaxCall(url, methodType)
   var promiseObj = new Promise(function(resolve, reject)
      var xhr = new XMLHttpRequest();
      xhr.open(methodType, url, true);
      xhr.send();
      xhr.onreadystatechange = function()
      if (xhr.readyState === 4)
         if (xhr.status === 200)
            console.log("xhr done ok");
            var response = xhr.responseText;
            var respJson = JSON.parse(response);
            resolve(respJson);
          else 
            reject(xhr.status);
            console.log("xhr failed");
         
       else 
         console.log("xhr processing");
      
   
   console.log("request sent succesfully");
 );
 return promiseObj;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
  <div id="app">
    <span>items</span>
    <ul>
      <li v-for="item in items.books" :key="item.name">-
        <span class="name">item.name</span>
        <br>
        <span class="genre">item.genre</span>
      </li>
    </ul>
  </div>
</template>

通常我会使用 jQuery,但我会使用其他东西。 我不知道如何在 $.get("books.json".. 有什么想法吗?

【问题讨论】:

【参考方案1】:

makeAjaxCall 函数移动到methods 部分,并将承诺结果分配给created 上的items

created: function() 
    this.makeAjaxCall("books.json", "get").then(res => 
        this.items = res
        return res
    )

我个人建议您使用一些更新的 ajax 请求技术,例如 fetch-apiaxios

【讨论】:

感谢您的帮助和建议。我一直在阅读有关 axios 的信息,它在我的愿望清单上。

以上是关于Vue中的Ajax的主要内容,如果未能解决你的问题,请参考以下文章

electron-vue项目中开发环境中的axios跨域问题

vue发布中的前后端分离和前后端不分离

python 前端框架和其他(155题)

前端VUE初学 求大佬指教这个demo如何通过ajax访问json文件然后传给data并渲染出来? 该怎么写?

vue续集2

带你重新认识 Ajax