我刚开始选择职业方向的时候我是主要想主攻android的,但是由于现在所在的公司正处于业务转型期:公司由以往主要做android平板定制任务到现在准备往前端等互联网上面转型。外加上我对很多语言稍有涉猎。然后就由我开始从零开始搭建一个vue前端的框架,现在网站的大体都出来了。主要的大功能包括:im、直播、另外包含一些后台登陆、权限系统、数据的增删改查等等。写这些文章呢?本意是想:
- 为同样处于初期的工程师一些指导,让看了我文章的工程师能够少花点时间在我做过的项目上面。
- 因为刚转vue前端,有很多的东西都不怎么懂,也希望与诸位看官一起讨论,相互学习 相互进步吧。
话不多说,现在开始谈一谈vue吧,因为我可能最近每天都会写着一个系列的文章,所以我现在写的东西并没有先后之分,如果我后来有时间。我会做一些简单的整理、更新。今天第一天就来谈一下 我对vue网络请求的一些封装吧。
今天第一天,我就从四个步骤去谈及这个东西吧,从头到尾依次是mock数据、代理、封装axios到最后的根据不同环境去访问不同分服务器的一系列工作吧。
一、 mock数据
有的时候,可能会存在一种情况--前端和后端同时开发的时候。传统的开发模式是等后端服务器全部开发的差不多了之后才开始去写前端。但是现在的前端和后端是分离开发的。所以还是这种思维就必定会处于落后的地位,并且我们现在本身在开发react native、vue等语言的时候本身就自己带一个nodejs的后台。既然本身就有一个后台,我就顺着这个思路去研究vue-cli(嗯,我是采用这个工具框架的)里面的配置文件,外加上一些大佬的协助下,终于找到了一个这个东西。
首先我查看vue的启动器,里面的代码是:
webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
然后我就顺着这个思路渠道webpack.dev.conf.js里面去找
const express = require('express')
const app = express()
const appData = require('../static/data/user.json')
const apiRouter = express.Router()
app.use('/api',apiRouter)
我就顺着build.js的意思,将一个json数据导入到数据中,然后把本地服务器的模拟数据的开头同意都写成api开头的数据,以便于管理。最后在本文件下面的devServer下面加入下面代码:
before(app) {
app.get('/api/user',(req, res) => {
res.json({
data: appData
})
})
}
最后打开http://localhost:8080/api/user就会得到user.json的内容了。当然这都只是为了本来调试方便而弄出来的
当然,当发展到一定的程度上面了,服务器已经弄好了部分接口,需要将数据从本地转移到正式的服务器上面 ,这时就要谈到所谓的代理了。
二、 代理
其实刚开始的时候,我在弄代理的时候,我遇到了很多的问题,比如跨域等问题。当然可能处于刚开始学习vue的你也可能存在这类问题。首先解释一下跨域的原因,我自己的理解就是:从一个域上加载的脚本不允许访问另外一个域的文档属性。我刚开始弄这个的时候很不理解,为什么会产生这个现象呢?这是android开发不可能存在的问题。
最后想了一想,也想通了,要是不存在跨域,那岂不是随便弄一个脚本就可以访问对方服务器。那么服务器早就会炸了。反正2014年的雅虎的事件历历在目(刚好在看黑客简史)。好了闲话不多说了。直接上代码吧。
这次我是找到index.js目录下面proxyTable下可以直接配置一个跨域的东西,当然有关proxyTable的具体,请查看proxyTable官网做详细了解,我这里就不画蛇添足了。主要是快一点了。紧接着我就顺着网上的教程直接配置:
'/lesson': {
target: 'http://xxx/v2/webapi/lesson', // 代理的网址
changeOrigin: true, // 允许跨域
pathRewrite: {
'^/lesson': '/'
}
}
然后通过axios进行get、post请求:
axios({
method: 'get',
url:'/lesson' ,
params: qs.stringify(data)
}).then(function (res) {
if (res) {
//...
}
});
}).catch(function (error) {
console.error(error);
})
最后发现根本不能访问到,最后几经纠缠,才发现原来是少了一个包 http-proxy-middleware。这个东西很强大,我刚开始的socket都是参考它文档使用跨域操作的,如果有兴趣也可以去参考了解一下。
三、 封装axios
也差不多12点了,我室友已经在骂我了。说实话今天刚去医院,我也渐渐写不下去了。我就直接上我的代码了。首先我对axios 进行封装(写安卓的一些习惯,一想到很多地方就会想封装)。直接上代码.
service.js:
import * as myapis from './apis'
const loginModule = {
login: {
url: myapis.LOGIN_URL, // 网址
method: 'post'
},
logout: {
url: myapis.LOGOUT_URL, // 网址
method: 'post'
}
}
const LoginApi = { ...loginModule }
myhttp.js:
import axios from 'axios'
import qs from 'qs'
import * as myapis from './apis'
import store from '../store'
import router from '../router'
axios.interceptors.request.use(config => {
if (store.state.token) {
config.headers.Authorization = store.state.token
}
return config
}, error => {
return Promise.reject(error)
})
axios.interceptors.response.use(response => {
return response
}, error => {
return Promise.resolve(error.response)
})
function errorState (res) {
return res
}
function successState (res) {
if (res && res.status === 200) {
return res.data
}
// if()
return '服务器值返回为空'
}
const httpServer = (opts, data) => {
let httpDefaultOpts = { // http默认配置
method: opts.method,
baseURL: myapis.BASE_URL,
url: opts.url,
timeout: 20000,
// responseType: 'json',
params: Object.assign(Public, data),
data: qs.stringify(Object.assign(Public, data)),
withCredentials: false,
headers: opts.method === 'get' ? {
'Accept': 'application/json',
' Content-Type': 'application/json; charset=UTF-8'
} : {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}
if (opts.method === 'get' && httpDefaultOpts.data) {
delete httpDefaultOpts.data
} else {
delete httpDefaultOpts.params
}
let promise = new Promise(function (resolve, reject) {
axios(httpDefaultOpts).then(
res => {
resolve(successState(res))
}
).catch(
error => {
reject(errorState(error))
}
)
})
return promise
}
export default httpServer
四、分环境访问
嗯,要睡觉了要睡觉了,就不扯了,反正也没人看。嗯,就这样。
想了一想,还是简单的介绍一下吧。我一共在config目录下面建了三个目录,共分为本地测试服务器、测试服务器、正式服务器三种。我 这里就拿测试服务器、正式服务器为例子。就当敲门砖吧:
prod.env.js :
'use strict'
module.exports = {
NODE_ENV: '"production"',
MY_MODE: '"prod"'
}
dev.env.js
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
MY_MODE: '"debug"'
})
mode.js
var url = process.env. MY_MODE
export default {
url
}
apis.js
import base from '../../config/mode'
let baseurl = ''
if (base.url === 'prod') {
// 正式
baseurl = 'http://prod...'
} else if (base.url === 'local') {
// 本地
baseurl = 'http://local...'
} else {
// 测试
baseurl = 'http://test...'
}
嗯,本次代码呢?写的并不是很深,可能很多的地方都存在着精进的地方。但是这是我一步一步自己的成果。如果对以上的内容存在有疑虑,请私聊、或者直接对本文进行评论。我看到了之后会对您的建议和疑惑做一一解答,之后我也会就这次网站的编写做一个系列的文章。对搭建一个框架(可能在很多人眼里都不算框架的东西)做一个代码的review。一是对我的知识点做回顾;二是希望能对同阶段的小伙子们有正向作用。
不扯了不扯了,要睡觉了。好困 呼呼~~