# Vue 中的 Ajax
# 1. vue 脚手架配置代理
web app 发送的请求通常都是 POST + JSON,解决跨域通常只有两种方式:
- 让目标服务器允许跨域访问,CORS(Cross-origin resource sharing,跨域资源共享)
- 绕过同源策略
- 使用 Nginx 的反向代理
- 将前端项目用后端项目包起来,在后端配置请求转发
# 1.1. 方法一
在 vue.config.js
中添加如下配置:
devServer:{
proxy:"http://localhost:5000"
}
说明:
- 优点:配置简单,请求资源时直接发给前端(8080)即可。
- 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
- 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)
# 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
*/
说明:
- 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
- 缺点:配置略微繁琐,请求资源时必须加前缀。
# 2. Github 用户搜索案例
App.vue:
<template>
<div class="box">
<Search />
<List />
</div>
</template>
Search.vue:
<template>
<div class="search">
search github users:
<input type="text" v-model="keyword" @keypress.enter="doSearch">
</div>
</template>
<script>
doSearch() {
this.$bus.$emit('getUsers', { users: [], errorMsg: '', isLoading: true });
axios.get(`https://api.github.com/search/users?q=${this.keyword}`)
.then((response) => {
const { items: users } = response.data;
this.$bus.$emit('getUsers', { users, errorMsg: '', isLoading: false });
})
.catch((e) => {
this.$bus.$emit('getUsers', { users: [], errorMsg: e.message, isLoading: false });
});
},
</script>
List.vue:
<template>
<div class="list">
<div v-show="model.users.length > 0"
v-for="user in model.users" :key="user.login" class="item"
>
<a :href="user.html_url" target="_blank"><img :src="user.avatar_url" alt=""></a>
<span>{{ user.login }}</span>
</div>
<!-- first -->
<div v-show="model.isFirst"><h2>欢迎使用</h2></div>
<!-- loading -->
<div v-show="model.isLoading"><img src="https://www.icegif.com/wp-content/uploads/loading-icegif-1.gif" alt=""></div>
<!-- error -->
<div v-show="model.errorMsg"><h2>{{ model.errorMsg }}</h2></div>
</div>
</template>
<script>
mounted() {
this.$bus.$on('getUsers', (data = { users: [], errorMsg: '', isLoading: false }) => {
this.model = {
...this.model,
...data,
isFirst: false,
};
});
},
data() {
return {
model: {
isFirst: true,
isLoading: false,
errorMsg: '',
users: [],
},
};
},
</script>
# 3. vue 项目中常用的 2 个 Ajax 库
axios: 通用的 Ajax 请求库, 官方推荐,使用广泛
vue-resource: vue 插件,vue1.x 使用广泛,官方已不维护,安装后 vue 原型上会多一个
$http
属性
# 4. 插槽
作用:让父组件可以向子组件指定位置插入 HTML 结构,也是一种组件间通信的方式,适用于父组件 ===> 子组件。
分类:默认插槽、具名插槽、作用域插槽
# 4.1. 默认插槽
将所有未分发的元素放入默认插槽
TestDefaultSlot.vue:
<template>
<div class="test-default-slot">
<div class="header">header</div>
<div class="body">
<slot>默认内容</slot>
</div>
<div class="footer">footer</div>
</div>
</template>
App.vue:
<template>
<!-- 没有标签体,则使用插槽的默认内容 -->
<TestDefaultSlot />
<!-- 使用自定义的内容,插入默认的插槽 -->
<TestDefaultSlot>自定义内容</TestDefaultSlot>
</template>
注意:
- 标签体的内容,既可以使用
App.vue
的局部样式,也可以使用TestDefaultSlot.vue
的局部样式
# 4.2. 具名插槽
将多个元素插入不同的位置
TestNamedSlot.vue:
<template>
<div class="test-box">
<div class="header">header</div>
<div class="body">
<slot name="body">body</slot>
</div>
<div class="footer">
<slot name="footer">footer</slot>
</div>
</div>
</template>
App.vue:
<!-- 基本使用 -->
<TestNamedSlot>
<div slot="body">111</div>
<div slot="footer">222</div>
</TestNamedSlot>
<!-- 挨个放入 body 插槽中 -->
<TestNamedSlot>
<div slot="body">333</div>
<div slot="body">444</div>
</TestNamedSlot>
<!-- 一个插槽,放入多个元素 -->
<TestNamedSlot>
<template slot="body">
<div>555</div>
<div>666</div>
</template>
</TestNamedSlot>
<!-- 一个插槽,放入多个元素,最新写法(只能用在 template 上) -->
<TestNamedSlot>
<template v-slot:body>
<div>777</div>
<div>888</div>
</template>
</TestNamedSlot>
<!-- # 为 v-slot 的简写 -->
<TestNamedSlot>
<template #body>
<div>999</div>
<div>000</div>
</template>
</TestNamedSlot>
# 4.3. 作用域插槽
数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。定义插槽时,暴露一些数据给使用者
TestScopeSlot.vue:
<template>
<div class="test-box">
<slot person-name="张三" :hobby="hobby">默认内容</slot>
</div>
</template>
<script>
export default {
data() {
return { hobby: ['看书', '看电影'] };
},
};
</script>
App.vue
<!-- scope 属性已被废弃 -->
<TestScopeSlot>
<template scope="scope">
<div>{{ scope.personName }} - {{ scope.hobby }}</div>
</template>
</TestScopeSlot>
<!-- 解构 -->
<TestScopeSlot>
<template slot-scope="{ personName, hobby }">
<div>{{ personName }} - {{ hobby }}</div>
</template>
</TestScopeSlot>
<!-- 新写法 -->
<TestScopeSlot>
<template v-slot:default="{ personName, hobby }">
<div>{{ personName }} - {{ hobby }}</div>
</template>
</TestScopeSlot>
<TestScopeSlot>
<template #default="{ personName, hobby }">
<div>{{ personName }} - {{ hobby }}</div>
</template>
</TestScopeSlot>
上一篇: 下一篇:
本章目录