情景介绍:公司中有一个类似单点登录的项目,主系统中有登录后username和token,存放在浏览器的cookies中,现在改造的子系统需要拿到这两个cookie值,再通过axios的设置header头部信息去向后端请求数据,由于使用了asyncData和nuxtServerInit方法,所以在服务端一开始就需要这两个数据,但是又拿不到客户端的cookie,查了很多资料
解决方案1 如下:这里使用Nuxt插件的方法封装Axios
步骤一:在plugins目录下新建axios-plugin.js
import axios from 'axios'
//开启浏览器端cookie传递
axios.defaults.withCredentials=true
const EDU_SERVER_API='http://127.0.0.1/api/v2';
let options = {};
options.baseURL = EDU_SERVER_API
let ax = { options:options, get: (req,url) => { options.headers = { "Cookie": req.headers.cookie+";" }
url=options.baseURL+url;
return axios.get(url,options); }}
// 为了在 asyncData 方法中使用
export default ({ app }, inject) => {
// Set the function directly on the context.app object
app.$global = {
ax:ax
}
};
步骤二 在Nuxt.config.js中新增plugins
plugins: [
'@/plugins/global',
{
src:'@/plugins/element-ui',
ssr: true,
},
'@/plugins/axios-plugin'
],
然后在AsyncData中使用
export default {
async asyncData(params) {
return params.app.$global.ax.get(params.req, '/user/').then(res => {
return {user: res.data.user};
})
}
}
解决方案2
介绍:使用中间件
1. 通过 express 取得 cookies
在 server.js 上引入 cookies 解析中间件
constcookieParser =require('cookie-parser')
并且在路由前面 use
app.use(cookieParser())
2. 将 cookies 注入 render 的上下文中
app.get('*', (req, res) => {// 其他代码省略constcontext = {url: req.url,cookies: req.cookies }constrenderStream = renderer.renderToStream(context)// 其他代码省略})
3. 将 cookies 注入 vuex 的 store 中
在server-entry.js文件中, 将 cookies 注入到 store 中
exportdefaultcontext => {// 其他代码省略if(context.cookies) { store.state.cookies = context.cookies }// 其他代码省略}
这样就可以在组件中取到 cookies 了.
4. 封装请求
这里以 axios 为例, 将 cookies 加载封装函数的参数中:
注意: 这里的封装, 建议将浏览器用的和 node 用的分开
importaxiosfrom'axios'constparseCookie =cookies=>{letcookie =''Object.keys(cookies).forEach(item=>{ cookie+= item +'='+ cookies[item] +'; '})returncookie}exportdefault{ get(url, params, cookies = {}) {constcookie = parseCookie(cookies)returnaxios({method:'get', url, params,headers: {'X-Requested-With':'XMLHttpRequest', cookie } }) }}
5. 发起带 cookies 参数的请求
在组件中 dispatch vuex 的 actions:
constfetchInitialData =async(store, config = {page:1}) => {awaitstore.dispatch('frontend/article/getList', config)}exportdefault{name:'frontend-index',prefetch: fetchInitialData,// 其他代码省略}
在 vuex 的 actions 中, 从 store 里读取 cookies, 作为参数传给请求接口的函数
async['getList']({commit,rootState: {cookies}}, config) {const{data: { data, code} } =awaitapi.get('/api/article/list', config, cookies)// 其他代码省略}
6. 几个注意点
1, cookies的内容中不允许带中文, 不知道从什么版本开始, http-server 的 header 里有中文就直接报错
2,import store from '../store'这种方式下的 store 是不会带 cookies 的
解决方案3(我使用的方案)
middleware下创建axiosMiddle.js
import axios from 'axios'
import md5 from 'js-md5'
import cookies from 'js-cookie'
export default function({req,res}) {
if (req.headers !== undefined) {
let cookieArr = req.headers.cookie;
//获取cookie然后拆成键值对
const getUserName = getCookie('name', cookieArr)
const getToken = getCookie('tiken', cookieArr)
//设置axios的全局变量.
axios.defaults.timeout = 60000 // 响应时间
// @requestParams
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
axios.defaults.headers.username = getUserName
axios.defaults.headers.token = getToken
axios.defaults.withCredentials = true
}
}
//解析浏览器中的cookies
function getCookie (name, strCookie) {
console.log('strCookie',strCookie)
var arrCookie = strCookie.split(';')
for (var i = 0; i < arrCookie.length; i++) {
var arr = arrCookie[i].split('=')
if (arr[0].trim() === name) {
return arr[1]
}
}
return {}
}
在nuxt.config,js中设置下使用中间件即可
router: {
middleware:'axiosMiddle'
},
至此,结束