第五篇利用vue实现了登录页面,用go语言开发了服务端并最后在nginx上进行了部署。本篇将axios封装,登录逻辑优化,404页面实现。
目录
1.前端
1.1代码结构
1.2源码
2.服务端
2.1源码
3.运行效果
4.注意事项
4.1webpack.config.js和vue.config.js的区别
4.2 npm run dev 与 npm run build
4.3ajax、Promise、axios总结
4.4Go语言处理跨域处理
1.前端
1.1代码结构
1.2源码
src/service.js
import axios from "axios";
import { getToken } from "@/utils/dealtoken.js"
import { Promise } from 'core-js'
import { Message } from "element-ui";// axios二次封装const service = axios.create({// baseURL还可以使用代理baseURL: 'http://127.0.0.1:8181', timeout: 3000
})// 请求拦截器
service.interceptors.request.use((config) => {//对请求做一些额外处理config.headers['token'] = getToken('token')config.headers['username'] = getToken('username')return config
}, (error) => {return Promise.reject(error)
})// 响应拦截器
service.interceptors.response.use((response) => {//对响应做一些处理let {status, msg} = response.dataif (status != 200) {Message({message: msg || 'error', type: 'warning'})}console.log(response, status, msg)return response
}, (error) => {return Promise.reject(error)
})export default service
src/main.js
import Vue from 'vue'
import App from './App'
import 'font-awesome/css/font-awesome.min.css'
//import axios from 'axios'
import router from './router'
import service from './service'// 挂载到原型就可以全局使用
//Vue.prototype.axios = axios
Vue.prototype.service = service
//Vue.config.productionTip = falseimport ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)new Vue({router,render: h => h(App)
}).$mount('#myapp')
router/index.js
import Vue from 'vue'
import Home from '@/components/Home'
import VueRouter from 'vue-router'Vue.use(VueRouter)const routes = [{ path: '/', redirect: '/login', component: () => import('@/components/Login') },{ path: '/login', name: 'Login', component: () => import('@/components/Login') },{ path: '/home', component: Home },{ path: '*', name: 'NotFound', component: () => import('@/components/NotFound') }
]export default new VueRouter({mode: 'history',routes: routes
})
src/api/api.js
//业务服务调用接口封装import service from '../service.js'export function login(data) {return service({method: 'post',url: '/login',data})
}
src/components/NotFound.vue
<template><div class="notfound"><div class="big">页面不见了!</div><div>首页瞧瞧,点击<router-link to="/">这里</router-link>进入首页.</div></div></template><script>export default {data() {return {};},};</script><style lang='scss'>.notfound {width: 100%;height: 100%;position: absolute;background: #409EFF;background: url('../assets/404page.jpg') center no-repeat;}</style>
src/components/Login.vue
<template><div class="login"><el-card class="box-card"><div slot="header" class="clearfix"><span>业务后台管理系统</span></div><el-form label-width="100px" :model="form" ref="form" :rules='rules'><el-form-item label="用户名" prop='username'><el-input v-model="form.username"></el-input></el-form-item><el-form-item label="密码" prop='password'><el-input type='password' v-model="form.password"></el-input></el-form-item><el-form-item><el-button type='primary' @click="login('form')">登录</el-button></el-form-item></el-form></el-card></div>
</template>/*
原生AJAX和Axios在使用上存在一定的区别。Axios可以支持多种方式,包括浏览器环境、node环境,而AJAX则只能在浏览器环境中使用。
Axios还支持多种请求方式,包括GET、POST、PUT、DELETE等;而AJAX只能支持GET和POST方式发送请求。此外,Axios还可以拦截请求和响应。
*/<script>//登录验证的封装
import {login} from '@/api/api.js'
import {nameRule, passRule} from '../utils/validate.js'
import {setToken} from '@/utils/dealtoken.js'export default {data () {return {form: {username: "",password: ""},rules: {username: [{validator: nameRule, required: true, trigger: "blur"}],password: [{validator: passRule, required: true, trigger: "blur"}]}}},methods: {login(form) {this.$refs[form].validate((valid) => {if (valid) {console.log(this.form)login(this.form).then(res => {if (res.data.status === 200) {setToken('token', res.data.token)setToken('username', res.data.Name)this.$message({message: res.data.msg, type: 'success'})this.$router.push('/home')}})} else {console.error(this.form)}})}}
}
</script><style lang='scss'>.login {width: 100%;height: 100%;position: absolute;//background: #409EFF;background: url('../assets/logo.png') center no-repeat;.el-card {background: #65768557;}.box-card {width: 450px;margin: 200px auto;color: #fff;.el-form .el-form-item_label {color: #fff;}.el-card_header {font-size: 34px;}.el-button {width: 100%;}}}
</style>
2.服务端
2.1源码
server.go
package mainimport ("main/controller""net/http""github.com/gin-contrib/cors""github.com/gin-gonic/gin"
)/*
// 错误: server.go:4:2: package main/controller is not in GOROOT (/home/tiger/go/go/src/main/controller)
go mod init main//错误: server.go:7:2: no required module provides package github.com/gin-gonic/gin; to add it:
go get github.com/gin-gonic/gin//处理跨域框架
go get github.com/gin-contrib/cors
*//*
当客户端(尤其是基于 Web 的客户端)想要访问 API 时,服务器会决定允许哪些客户端发送请求。这是通过使用称为 CORS 来完成的,它代表跨源资源共享。
跨域资源共享 (CORS) 是一种机制,允许从提供第一个资源的域之外的另一个域请求网页上的受限资源。
*/func CrosHandler() gin.HandlerFunc {return func(context *gin.Context) {context.Writer.Header().Set("Access-Control-Allow-Origin", "*")context.Header("Access-Control-Allow-Origin", "*") // 设置允许访问所有域context.Header("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE,UPDATE")context.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma,token,openid,opentoken")context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")context.Header("Access-Control-Max-Age", "172800")context.Header("Access-Control-Allow-Credentials", "true")context.Set("content-type", "application/json") //设置返回格式是json//处理请求context.Next()}
}// http://127.0.0.1:8181/ping
// http://127.0.0.1:8181/index
func main() {r := gin.Default()// 设置全局跨域访问//r.Use(CrosHandler())//cors处理跨域corsConfig := cors.DefaultConfig()corsConfig.AllowCredentials = truecorsConfig.AllowHeaders = []string{"content-type", "Origin", "token", "username"}corsConfig.AllowOrigins = []string{"http://localhost:8080"}r.Use(cors.New(corsConfig))//r.Use(cors.Default())// 返回一个json数据r.GET("/ping", func(c *gin.Context) {c.JSON(200, gin.H{"message": "pong","num": 888,})})// 返回一个html页面r.LoadHTMLGlob("templates/*")r.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)})r.POST("/login", controller.LoginPost)r.POST("/formlogin", controller.FormLoginPost)r.POST("/upload", controller.UploadFile)//r.Run() // <===> r.Run(":8080") 监听并在 0.0.0.0:8080 上启动服务r.Run(":8181")
}
controller/login.go
package controllerimport ("encoding/json""fmt""io/ioutil""net/http""path/filepath""github.com/gin-gonic/gin"
)// post http://127.0.0.1:8181/login
// axios.post 和 post json处理
func LoginPost(ctx *gin.Context) {version := ctx.DefaultQuery("version", "V1.0.0.1")//前端使用axios直接传递form时,axios会默认使用json,必须使用下面方式获取json数据,解析后再使用data, _ := ioutil.ReadAll(ctx.Request.Body)type UserInfo struct {Username stringPassword string}var u UserInfoerr := json.Unmarshal(data, &u)if err != nil {fmt.Println(err)}username := u.Usernamepassword := u.Passwordfmt.Println("login info:: ", version, username, password)if username == "123456" && password == "1234abcdE@" {ctx.JSON(http.StatusOK, gin.H{"status": 200,"Name": username,"Password": password,"msg": "登录成功","token": "abcd1234ABCD",})} else {ctx.JSON(http.StatusOK, gin.H{"status": -1,"Name": username,"Password": password,"msg": "用户名或密码错误",})}
}// http://127.0.0.1:8181/formlogin
// form表单提交处理 application/x-www-form-urlencoded 或者 application/form-data
func FormLoginPost(ctx *gin.Context) {username := ctx.PostForm("username")password := ctx.PostForm("password")fmt.Println("FormLoginPost :: ", username, password)if username == "123456" && password == "1234abcdE@" {ctx.JSON(http.StatusOK, gin.H{"status": 200,"Name": username,"Password": password,"msg": "登录成功","token": "abcd1234ABCD",})} else {ctx.JSON(http.StatusOK, gin.H{"status": -1,"Name": username,"Password": password,"msg": "用户名或密码错误",})}
}// form表单提交文件上传处理 multipart/form-data
func UploadFile(ctx *gin.Context) {file, _ := ctx.FormFile("uploadfile")fmt.Println(file.Filename)file_path := "upload/" + filepath.Base(file.Filename)fmt.Println(file_path)ctx.SaveUploadedFile(file, file_path)ctx.String(http.StatusOK, "上传成功")
}
3.运行效果
4.注意事项
4.1webpack.config.js和vue.config.js的区别
webpack.config.js是webpack的配置文件,所有使用webpack作为打包工具的项目都是可以创建这个文件使用的,Vue /react项目都可以。
vue.config.js是Vue项目的配置文件,通过这个文件配置Vue项目中常用的功能,简化了配置工作,也可以直接写一些关于webpack的配置,当然如果需要更加专业的配置,这两个文件在Vue的项目中也是可以共存的。
用 vue-cli-service serve 启动就会用 vue.config.js;
用 webpack-dev-server 启动就会用 wepback.config.js(默认)。
vue.config.js 是 Vue CLI 3.x 中一个重要的配置文件,用于对项目进行全局的配置。这个文件不存在,需要手动创建,与 package.json 文件同级。通过 vue.config.js 文件的配置,我们可以实现很多高级功能,例如 Webpack 的各项配置、跨域代理、目录别名等等。
4.2 npm run dev 与 npm run build
当在控制台执行npm run dev 与 npm run build时,其实npm是读取package.json中scripts进行真正的程序执行
4.3ajax、Promise、axios总结
promise是一种异步机制的解决方案。axios是一个基于promise方案封装的网络请求库,它是基于XHR进行二次封装。
axios可以说是XHR的一个子集,而XHR又是ajax的一个子集
axios是ajax,ajax不止axios;axios有的ajax都有,ajax有的axios不一定有。
4.4Go语言处理跨域处理
corsConfig := cors.DefaultConfig()
corsConfig.AllowCredentials = true
corsConfig.AllowHeaders = []string{"content-type", "Origin", "token", "username"}
corsConfig.AllowOrigins = []string{"http://localhost:8080"}r.Use(cors.New(corsConfig))