Vue前端页面开发
环境搭建
-
利用@vue/cli4创建工程,为兼容element-ui选用vue2.x版本
vue create vue-demo
-
添加element-ui框架
cd vue-demo vue add element
上述命令会安装element-ui插件,不用在入口
main.js
文件配置如下内容:import ElementUI from 'element-ui import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI)
-
安装axios库
npm install axios -S
在入口
main.js
文件配置axios:var axios = require('axios') // 设置请求的基本链接,如果需要跨域不能直接设置为服务器接口api //axios.defaults.baseURL = '/api' // 全局注册axios,之后在组件中通过this.$axios发送请求 Vue.prototype.$axios = axios
创建登录页面
-
修改App.vue根组件
<template> <div id="app"> <router-view></router-view> </div> </template>
同路由相匹配的子组件将在
<router-view>
标签渲染 -
创建Login.vue组件
<template> <body class = "login_bg"> <div class = "login_container"> <el-form ref="LoginForm" :model="LoginForm" label-width="80px"> <h2 class = "login_title">登录</h2> <el-form-item label="用户名"> <el-input v-model="LoginForm.username"></el-input> </el-form-item> <el-form-item label="密码"> <el-input v-model="LoginForm.password"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click = "login">登录</el-button> <el-button @click = "goToRegist">注册</el-button> </el-form-item> </el-form> </div> </body> </template> <script> export default { name: 'Login', data() { return { LoginForm: { username: '', password: '' } } }, methods: { // 登录 login(){ this.$axios.post('/api/login', `username=${this.LoginForm.username}&password=${this.LoginForm.password}`).then(successResponse => { // 后端发送过来的是 Result 类型数据,判断 Result.code 即可 if(successResponse.data.code === 200){ // 触发 store 中的 login() 方法,将 LoginForm.username 字段传递给 store 中的 username this.$store.commit('login', this.LoginForm) var path = this.$route.query.redirect this.$router.replace({path: path === '/' || path === undefined ? '/index' : path}) } else { this.$alert(successResponse.data.message, '😔 Failed', { confirmButtonText: '确定' }) } }).catch(failResponse => { }) }, // 进入 regist 界面 goToRegist(){ this.$router.replace({path: '/regist'}) } } } </script> <style scoped> .login_container { border-radius: 20px; background-clip: padding-box; margin: 130px auto; width: 400px; padding: 35px 65px 15px 0px; background: #fff; border: 1px solid #cfc9c9; } .login_title { margin: 0px 0px 40px 75px; text-align: center; color: #505458; font-size: 32px; } </style>
在vue环境中this指向vue实例,但在vue中使用axios发起请求时如果then和catch方法直接传入非箭头函数形式的匿名函数时,this将指向undefined。
第一种解决方案:
var _this = this
发送请求前保留this引用,后面使用_this访问vue实例
第二种解决方案:
在then或catch方法中使用箭头函数形式的匿名函数
-
使用vuex管理全局状态
export default new Vuex.Store({ state: { user: { username: window.localStorage.getItem('user') == null ? '' : JSON.parse(window.localStorage.getItem('user')).username } }, mutations: { login(state, data) { state.user = data window.localStorage.setItem('user', JSON.stringify(data)) } }, actions: { }, modules: { } })
如果状态变化,通过
this.$store.commit
方法修改 -
配置路由
const routes = [ { path: '/index', name: 'Index', component: Index, meta: { requireAuth: true } }, { path: '/login', name: 'Login', component: Login } ]
如果使用嵌套路由,嵌套路由仅表示组件的父子关系,与URL地址无关
-
配置前端路由拦截器
main.js
入口文件设置拦截器:router.beforeEach((to, from, next) => { if (to.meta.requireAuth) { if (store.state.user.username) { next() } else { next({ path: 'login', query: {redirect: to.fullPath} }) } } else { next() } } )
to
表示目标路由对象,form
表示源路由对象,next
应保证逻辑代码执行完后被调用一次
跨域设置
代理解决跨域的原理是:浏览器的同源策略仅限制浏览器与服务器交互,服务器与服务器交互不受同源策略影响
根目录创建vue.config.js
文件,配置如下:
module.exports = {
devServer: {
proxy: { // 跨域支持
"/api": {
target: "http://localhost:8081", //API服务器的地址(后端)
changeOrigin: true, // 虚拟的站点需要更管 origin
pathRewrite: {
//重写路径 比如 '/api/aaa/ccc'对应后端接口 '/aaa/ccc'
"^/api": "",
},
},
},
}};
target
表示服务器接口地址
pathRewrite
会重写地址,比如上面代码会将发送到/api/login
的请求代理到http://localhost:8081/login
。这样做的好处是只有/api
开头的请求会被代理,这样可以避免静态资源被代理
设置完代理后,只有从本机发起的请求(同域名、同端口)会被代理。如果axios的baseurl与前端服务器不同源,则axios发起的请求不会被代理,造成跨域失败