普通视图

发现新文章,点击刷新页面。
今天 — 2026年1月24日首页

nuxt配置代理 和 请求接口

作者 江湖文人
2026年1月24日 15:45
一、安装

npm install @nuxtjs/axios @nuxtjs/proxy -S


// nuxt.config.js
{
  ...
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/proxy'
  ],
  axios: {
    // 是否可以跨域
    proxy: true,
    // retry: { retries: 3 },
    // baseUrl: process.env._ENV == 'production' ? 'xxx' : 'xxx'
  },
  proxy: {
    '/api': {
      target: 'http://localhost:4000',
      pathRewrite: {
        '^/api': ''
      }
    }
  }
}

image.png

登录&获取个人信息

axiaos在项目中一定会进行二次封装的。封装的内容可能有所不同。

登录 我的 新闻

点击登录,它就跳转到登录页,那在登录页我就可以输入账号或者密码。当然,在正儿八经的项目里面,可能会有扫码登录或者验证码等等。所以我们先做个简易版的,先把逻辑走通先。就是用户名和密码登录。如果说它输入内容登录上了以后,就需要把token记录上。

存储之后,如果说他已经登录了,那点击到我的,它可以展示这个登录账号的一个头像或者昵称等等信息。如果说没有登录,点到我的,它会跳转到登录页,

当然新闻的话呢,是不需要登录的。就是登录没邓旒都可以进入到新闻页。

/pages/index.vue

<template>
  <div>
    <nuxt-link to="/login">登录</nuxt-link>
    <nuxt-link to="/my">我的</nuxt-link>
    <nuxt-link to="/news">新闻</nuxt-link>
  </div>
</template>

<script>
export default {
  name: 'IndexPage'
}
</script>

登录页

// login.vue
<template>
  <div>
    <h1>登录页</h1>
    <input v-model="userName" />
    <input v-model="userPwd" />
    <button @click="login">登录</button>
  </div>
</template>

<script>
export default {
  return {
      userName: '',
      userPwd: ''
  },
  methods: {
    login() {
    }
  }
}
</script>

然后安装包

cnpm install @nuxtjs/axios @nuxtjs/proxy -Ss

到config里面去配置:

// nuxt.config.js

{
  ...
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/proxy'
  ],
  axios: {
    proxy: true
  },
  // 代理的地址
  proxy: {
    '/api': {
      // 一般这里填域名 
      target: 'http://testapi.xxx.cn/'
    }
  }
}

然后就可以写接口了:

// login.vue
<template>
  <div>
    <h1>登录页</h1>
    <input v-model="userName" />
    <input v-model="userPwd" />
    <button @click="login">登录</button>
  </div>
</template>

<script>
export default {
  return {
      userName: '',
      userPwd: ''
  },
  methods: {
    login() {
      this.$axios({
        url: '/api/u/loginByJson',
        method: 'post'
      })
    }
  }
}
</script>

这里需要qs一下:

cnpm install qs -S
// login.vue
<template>
  <div>
    <h1>登录页</h1>
    <input v-model="userName" />
    <input v-model="userPwd" />
    <button @click="login">登录</button>
  </div>
</template>

<script>
export default {
  return {
      userName: '',
      userPwd: ''
  },
  methods: {
    login() {
      let data = qs.stringify({
        username:  this.userName,
        password: this.userPwd
      })
      this.$axios({
        url: '/api/u/loginByJson',
        method: 'post',
        data
      }).then(res => {
        console.log(res)
      })
    }
  }
}
</script>

qs用来处理url查询字符串的序列化和解析。

解析

将url查询字符串转为js对象:

import qs from 'qs';

const query = '?name=张三&age=21';
const result = qs.parse(query, { ignoreQueryPrefix: true });

// 结果:{ name: '张三', age: '21' }

序列化

将js对象转换为url查询字符串

const obj = {
  name: '张三',
  age: 21,
  hobbies: ['1', '2']
}
const queryString = qs.stringify(obj);
// 结果 'name=张三&age=21$hobbies=1$hobbies=2'
// 嵌套对象
qs.stringify({ a: { b: { c: 'value' } } });
// 结果:'a[b][c]=value'

// 支持数组索引
qs.stringify({ a: [1, 2, 3] });
// 结果:'a[0]=1&a[1]=2&a[2]=3'
qs.stringify(obj, {
  encode: true,      // 是否编码(默认true)
  arrayFormat: 'brackets',  // 数组格式:indices/brackets/repeat
  skipNulls: true,   // 跳过null值
  allowDots: true,   // 使用点号表示嵌套:a.b.c=value
});

在请求中,为什么还要用一下qs.stringify()为了将对象正确地格式化为application/x-www-form-urlencoded格式。

解决axios默认行为问题。

axios默认情况下:

  • 当data是对象时,会自动序列化为application/json(json格式)。

  • 有些后端接口要求application/x-www-form-urlencoded格式。

qs.stringfy({
  username: '张三',
  password: '123'
})

// 结果 'username=%E5%BC%A0%E4%B8%89&password=123456'

请求头: Content-Type: application/x-www-form-urlencoded

image.png

登录成功后有一个token:

然后就需要把token给存储起来。下一步做的事就是如果我登录成功了,肯定要把token存进去,存到vuex里面,并且做到持久化存储。

点击我的,会显示个人信息在里边。获取个人信息。获取个人信息,需要把token携带过去。就有这样一个参数。这个时候就要针对axios进行二次封装了。

那么封装的内容就要在plugins里面。

// nuxt.config.ts

{
  ...
  plugins: [
    '~/plugins/axios'
  ],
  ...
}

plugins/axios.js

// axios.js
export default ({ $axios, store }) => {
  // Request拦截器,设置token
  $axios.onRequest((config) => {
    
  })
  $axios.onRequest((error) => {
    
  })
  $axios.onResponse((response) => {
    return response.data;
  })
}

二次封装封装的点特别多,比如说我们可以封装它的一个request拦截器去设置一个token

image.png

在store下面设置vuex:

export const state = {
  token: ''
}

// 因为要做服务端,服务端因为没有localstorage\cookie等,所以需要安装 cnpm install cookie-universal-nuxt -S
export const mutations = {
  setToken(state, token) {
    state.token = token
    this.$cookies.set('token', token);
  },
  getToken(state) {
    // 这里用中间件读取到token,然后在这个方法里面去设置token
    state.token = this.$cookies.get('token');
  }
}

并且要把cookie-universal-nuxt配置到modules里面:

// nuxt.config.js
{
  ...
  modules: [
   'cookie-universal-nuxt'
  ]
}

设置完成后,回到任何一个地方,它都有。然后我们需要认证守卫。

在这里我们需要把中间件创建一下,先在根目录创建middleware文件夹,然后在这下面创建一个auth.js文件,

在my页面做middleware:

// my.vue
<template>
  <div>
    <h1>我的</h1>
  </div>
</template>

<script>
export default{
  middleware: 'auth'
}
</scirpt>

middlewaremy页面生效。这是我们读取出来的store

// middleware/auth.js
export default ({ store }) => {
  console.log(store.state);
}

然后获取token的值,我们已经持久化存到cookie了,可以commit去提交那个getToken

// middleware/auth.js
export default ({ store }) => {
  store.commit('getToken');
  console.log(store.state);
}

然后就可以读取得到token了。

如果没有token的,就让他跳转到登录页:

// middleware/auth.js
export default ({ store, redirect }) => {
  store.commit('getToken');
  console.log(store.state);
  if (!store.state.token) {
    redirect('/login')
  }
}
// login.vue

methods: {
  ...mapMutations(['setToken']),
  login() {
    let data = qs.stringify({
      username: this.userName,
      password: this.userPwd
    });
    
    this.$axios({
      url: '/api/u/loginByJson',
      method: 'post',
      data
    }).then(res => {
      this.setToken(res.data.accessToken)
      this.$router.push({
        name: 'index'
      })
    })
  }
}

如果没有登录,那么点击我的就会进入登录页,登录也填入账号和密码,点击登录,就会请求登录接口,然后获得token,token就会设置到cookie里面,再点击我的,就会可以查看自己的信息了,然后state.token会在中间件里又把本地cookie里面的token设置回去给它(完成持久性)。

做完之后,在我的页面,想要获得到个人信息,用户信息,所以在my.vue就可以做文章了:

// my.vue

<template>
  <div>
    <h1>我的</h1>
  </div>
</template>

<script type="text/javascript">
export default {
  middleware: 'auth',
  async asyncData({ $axios }) {
    let res = await $axios.get('/api/member/getInfo');
    console.log(res);
  }
}
</script>

请求的axios要全局封装,一定要带token:

// axios.js
export default ({ $axios }) => {
  // Request拦截器,设置token
  $axios.onRequest((config) => {
    config.headers['Authorization'] = store.state.token;
  })
  // Error拦截器:出现错误的时候被调用
  $axios.onRequest((error) => {
    consolelog(222, error);
  })
  $axios.onResponse((response) => {
    console.log(333, response)
    return response.data
  })
}
❌
❌