欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Vue项目实战踩坑(vue-cli3+axios跨域问题)

程序员文章站 2022-07-10 16:11:00
...

Vue项目实战踩坑(vue-cli3+axios跨域问题)
下面简单介绍一下我们的后台部分,后台运行在本地,总体框架使用springboot,使用8088端口,满足简单的crud操作,下面开始vuei项目的初始化,首先在全局安装@vue/cli的情况下,进行项目的初始化
使用命令行工具进入到我们的项目目录,然后使用指令初始化项目

vue create vue-cli-2

Vue项目实战踩坑(vue-cli3+axios跨域问题)具体的安装流程初次安装应该有些麻烦,但是在这里不再赘述,因为完全可以在b站找个vue教学视频学习,创建完毕以后,我们会得到一个项目目录,对于vue-cli4的情况下,我们的项目目录下会有一个main,js我们需要在这里完成需要导入的js和插件,还有一个app.vue这是官方默认装载在首页的组件,这一点可以在main.js的vue实例中看出来

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

那么,接下来,我们先运行一下项目,看看效果,执行指令

npm run build

这样就能构建成功,可以注意查看控制台的信息,接下来运行项目

npm run serve

Vue项目实战踩坑(vue-cli3+axios跨域问题)项目成功运行,我们可以在浏览器打开页面,下面我们进行一些改造,第一个就是,我们要改变项目初始化加载的组件,我们先创建一个组件login.vue,他其实是一个登录页,具体信息如下

<template>

    <div class="login-container">
        <el-form :model="ruleForm2" :rules="rules2"
         status-icon
         ref="ruleForm2" 
         label-position="left" 
         label-width="0px" 
         class="demo-ruleForm login-page">
            <h3 class="title">系统登录</h3>
            <el-form-item prop="username">
                <el-input type="text" 
                    v-model="ruleForm2.username" 
                    auto-complete="off" 
                    placeholder="用户名"
                ></el-input>
            </el-form-item>
                <el-form-item prop="password">
                    <el-input type="password" 
                        v-model="ruleForm2.password" 
                        auto-complete="off" 
                        placeholder="密码"
                    ></el-input>
                </el-form-item>
            <el-checkbox 
                v-model="checked"
                class="rememberme"
            >记住密码</el-checkbox>
            <el-form-item style="width:100%;">
                <el-button type="primary" style="width:100%;" @click="handleSubmit" :loading="logining">登录</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
export default {
    data(){
        return {
            logining: false,
            ruleForm2: {
                username: 'admin',
                password: '123456',
            },
            rules2: {
                username: [{required: true, message: 'please enter your account', trigger: 'blur'}],
                password: [{required: true, message: 'enter your password', trigger: 'blur'}]
            },
            checked: false
        }
    },
    methods: {
        handleSubmit(event){
            this.$refs.ruleForm2.validate((valid) => {
                if(valid){
                    this.logining = true;
					this.$axios.get('/user/login?username='+this.ruleForm2.username+'&password='+this.ruleForm2.password).then((data)=>{
						//在这里需要使用箭头函数,保证我们的this依旧指向原想的vue实例
						//进入到这一步只能表示登录请求发送成功
						//验证结果要看data里面的code
						//100---成功
						//200---失败
						this.$alert(data.data.data.msg, '老肖的提示', {
						    confirmButtonText: '确定'
						});
						if(data.data.code==100){
							//this.logining用来处理那个加载的小图标
							this.logining = false;
							this.$router.push({path:'/default'})
						}
						else{
							this.logining = false;
						}
					}).catch((error)=>{
						console.log(error)
						this.$alert('网络请求问题,联系管理员修复', '老肖的提示', {
						    confirmButtonText: '确定'
						});
					})
                }else{
                    console.log('error submit!');
                    return false;
                }
            })
        }
    }
};
</script>

<style scoped>
.login-container {
    width: 100%;
    height: 100%;
	margin-top: 0 auto;
}
.login-page {
    -webkit-border-radius: 5px;
    border-radius: 5px;
    margin: 180px auto;
    width: 350px;
    padding: 35px 35px 15px;
    background: #fff;
    border: 1px solid #eaeaea;
    box-shadow: 0 0 25px #cac6c6;
}
.title{
	text-align: center;
}
label.el-checkbox.rememberme {
    margin: 0px 0px 15px;
    text-align: left;
}
.v-enter,
.v-leave-to{
	opacity: 0;
	transform: translateX(80px);
}
.v-enter-active,
.v-leave-active{
	transition: all 0.6s ease;
}
</style>

下面,要使用改变路由的方式切换到login.vue,首先我们要创建路由信息,项目src/router下面有一个index.js,这里定义着我们的单页面应用所需要的所有路由信息

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/login.vue' //添加

Vue.use(VueRouter)

const routes = [
	{ //添加
		path:'/login',
		component:Login
	} //添加
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

在这里,我们设置了这样一个路由,下面我们再vue组件中使用它
在组件中定义一个钩子函数mounted,在这里将路由push到login即可,但是这有一个问题,因为我们在login.vue中使用了element-ui,但是我们还未引入,所以要先导入这个插件库,首先本地安装element-ui,并且启用服务

npm install element-ui -D

然后,我们在我们的main.js中引用element-ui,并且启用它
下面是main,js的内容

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Element from 'element-ui'  //添加
import 'element-ui/lib/theme-chalk/index.css' 添加

Vue.use(Element) //添加
Vue.config.productionTip = false

new Vue({
	mounted:function(){
		this.$router.push({path:'/login'})
	},
  router,
  store,
  render: h => h(App)
}).$mount('#app')

Vue项目实战踩坑(vue-cli3+axios跨域问题)这样就有了首页,也就是登录页
下面进入今天的主题,登录肯定要经过后台验证,后台已经写好了接口我们可以先使用postman进行登录测试
Vue项目实战踩坑(vue-cli3+axios跨域问题)请注意,此时我们登录请求的url是

localhost:8088/user/login?username=admin&password=123456

现在我们先引入axios模块,完成请求结构的构建

npm install axios -D

接下来,我们在main.js中简单配置我们的axios

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import axios from 'axios'  //添加

Vue.prototype.$axios = axios  //添加
axios.defaults.baseURL = '/api'  //添加
axios.defaults.headers.post['Content-Type'] = 'application/json'  //添加

Vue.use(Element)
Vue.config.productionTip = false

new Vue({
	mounted:function(){
		this.$router.push({path:'/login'})
	},
  router,
  store,
  render: h => h(App)
}).$mount('#app')

Vue.prototype.$axios = axios这一步,我们将axios配置到this中,方便我们可以在组件中使用axios发请求
axios.defaults.baseURL = '/api’这一步,我们给每一个请求加上了一个根,举个例子原来请求localhost:8080/admin/login---->localhost:8080/api/admin/login,也就是每个请求都在主机后面加一个api,这个用处以后介绍
axios.defaults.headers.post[‘Content-Type’] = ‘application/json’,这一步则配置了一个请求头,接下来我们测试登录请求能否触发
,因为在组件的定义过的登陆方法

this.$axios.get('/user/login?username='+this.ruleForm2.username+'&password='+this.ruleForm2.password).then((data)=>{
						//在这里需要使用箭头函数,保证我们的this依旧指向原想的vue实例
						//进入到这一步只能表示登录请求发送成功
						//验证结果要看data里面的code
						//100---成功
						//200---失败
						this.$alert(data.data.data.msg, '老肖的提示', {
						    confirmButtonText: '确定'
						});
						if(data.data.code==100){
							//this.logining用来处理那个加载的小图标
							this.logining = false;
							this.$router.push({path:'/default'})
						}
						else{
							this.logining = false;
						}
					}).catch((error)=>{
						console.log(error)
						this.$alert('网络请求问题,联系管理员修复', '老肖的提示', {
						    confirmButtonText: '确定'
						});
					})

我们打开浏览器的控制台,我们点击登录按钮,可以看到一个404的请求
Vue项目实战踩坑(vue-cli3+axios跨域问题)不难看出,此时我们的请求链接是

http://localhost:8080/api/user/login?username=admin&password=123456

这样做其实会跨域因为我们接了一个根/api的原因,变成了404,如果没有配置/api的情况下,我们会发生跨域,为了解决这个问题,我们现在项目根目录创建一个文件vue.config.js
内容如下

module.exports = {
	devServer: {
		open: false,
		port: 8080,
		https: false,
		proxy: {
			'api': {
				target: 'http://localhost:8088/',
				ws: true,  //开启跨域
				changeOrigin: true,
				pathRewrite: {
					'^/api':''
				}
			}
		}
	}
};

可以看到,我们在这里使用proxy,配置了一个代理。名字是api,在这个代理中,我们配置了一个taget, 还有一个pathRewrite, pathRewrite里面的内容表示,但我们发现请求中含有api时,我们会将请求中/api和之前的内容替换成target中的内容,接上一个例子
那么最终的请求是localhost:8088/admin/login,确实神奇,下面验证我的说法,先重新构建项目,在启动

npm run build
npm run serve

之后,再次点击登录按钮,我们就能看到,请求已然变成了200,即,我们的请求成功了
Vue项目实战踩坑(vue-cli3+axios跨域问题)今天这个跨域问题折腾了半天,记录下来,明天继续写项目