最近从零到一开发了一个门户网站,因对seo有要求,所以选择nuxt.js搭配typescript,期间遇到不少问题,最终都一一解决了,留下一个demo供参考,如果能帮到大家,帮忙给个star,感谢!demo地址
以下是我的部分总结(后续抽空会再补充):
一、axios
建议直接使用nuxtjs
的axios
模块。
1.安装并引入@nuxtjs/axios
需要代理请一并安装引入@nuxtjs/proxy
nuxt.config.js中:
export default {
modules:[
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
axios: {
proxy: true,
baseURL: '',
prefix: '/api-prefix',
credential: true
},
proxy: {
'/api-prefix': {
target: 'http://...',
changeOrigin: true,
pathRewrite: {
'^/api-prefix': '',
changeOrigin: true
}
}
},
...
}
2.axios拦截
在plugins
目录下,新增axios-accessor.ts
文件:
plugins/axios-accessor.ts中:
import { Plugin } from '@nuxt/types'
import { AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios'
const accessor: Plugin = ({ error }) => {
$axios.onRequest((config: AxiosRequestConfig) => {
// ...
return config
})
$axios.onError((e: AxiosError) => {
// ...
})
// response拦截器,数据返回后,你可以先在这里进行一个简单的判断
$axios.interceptors.response.use((response: AxiosResponse) => {
const res = response
if (res.status === 200) {
return Promise.resolve(res)
} else {
return Promise.reject(res)
}
},
(e: any) => {
const { status, data } = e.response
error({ statusCode: status, message: data })
return Promise.reject(e)
})
}
export default accessor
然后应用新增的plugin/axios-accessor.ts
nuxt.config.js中新增如下配置:
export default {
...
plugins: [
'@/plugins/axios-accessor'
]
}
3.非vue文件中使用$axios
对象
nuxtjs
中的axios模块会在vue实例上挂载一个$axios
对象供使用,实际开发过程中,我们往往习惯将项目中api方法放在单独的模块供全局使用,如何在非vue文件中使用$axios
对象呢?
nuxtjs
官网提供的typescript
文档中,在vuex的store初始化示例中,有一并讲到,传送门:https://typescript.nuxtjs.org...
utils/api.ts中:
import { NuxtAxiosInstance } from '@nuxtjs/axios'
let $axios: NuxtAxiosInstance
export function initializeAxios (axiosInstance: NuxtAxiosInstance) {
$axios = axiosInstance
}
export { $axios }
plugin/axios-accessor.ts中:
import { Plugin } from '@nuxt/types'
import { AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios'
// 新增引入
import { initializeAxios } from '~/utils/api'
const accessor: Plugin = ({ error, app: { $axios } }) => {
// 此处调用
initializeAxios($axios)
$axios.onRequest((config: AxiosRequestConfig) => {
// ...
return config
})
$axios.onError((e: AxiosError) => {
// ...
})
// response拦截器,数据返回后,你可以先在这里进行一个简单的判断
$axios.interceptors.response.use((response: AxiosResponse) => {
const res = response
if (res.status === 200) {
return Promise.resolve(res)
} else {
return Promise.reject(res)
}
},
(e: any) => {
const { status, data } = e.response
error({ statusCode: status, message: data })
return Promise.reject(e)
})
}
大功告成,后续在其他文件中,只需:import { $axios } from '@/utils/api'
就可以直接使用啦!
二、store
如nuxtjs
官方文档所说,Nuxt.js
支持两种使用 store
的方式,你可以择一使用:
- 模块方式:
store
目录下的每个.js
文件会被转换成为状态树指定命名的子模块 (当然,index
是根模块) - Classic(不建议使用):
store/index.js
返回创建Vuex.Store实例的方法。
结合ts当然是使用 vuex-module-decorators来创建modules。
store/myModule.ts中:
import { Module, VuexModule, Mutation } from 'vuex-module-decorators'
@Module({
name: 'myModule',
stateFactory: true,
namespaced: true,
})
export default class MyModule extends VuexModule {
wheels = 2
@Mutation
incrWheels(extra) {
this.wheels += extra
}
get axles() {
return this.wheels / 2
}
}
utils/store-accessor.ts中:
import { Store } from 'vuex'
import { getModule } from 'vuex-module-decorators'
import MyModule from '~/store/myModule'
let myModule: MyModule
function initialiseStores(store: Store): void {
myModule = getModule(MyModule, store)
}
export { initialiseStores, myModule }
store/index.ts中:
import { Store } from 'vuex'
import { initialiseStores } from '~/utils/store-accessor'
const initializer = (store: Store) => initialiseStores(store)
export const plugins = [initializer]
export * from '~/utils/store-accessor'
然后就可以愉快的使用啦!
三、cookie
关于cookie这一块,以前一直用的是js-cookie这个库,这次的nuxtjs项目中,mode: 'universal'
模式下,服务端渲染时没办法获取到客户端缓存的cookie,导致页面刷新后无法立即通过cookie拿到用户缓存的登录状态,因此后来改用cookie-universal-nuxt
这个库,api与js-cookie基本一致,可在服务端使用,引入后,会在vue实例上新增一个 $cookie
对象,为方便全局使用,可仿照$axios的accessor逻辑,如下example:
1.首先安装并引入
npm install cookie-universal-nuxt --save
nuxt.config.js中:
export default {
module: [
'@nuxtjs/axios',
'@nuxtjs/proxy',
'cookie-universal-nuxt'
],
...
}
2.cookie的accossor
utils/api.ts中:
import { NuxtAxiosInstance } from '@nuxtjs/axios'
import { NuxtCookies } from 'cookie-universal-nuxt'
let $axios: NuxtAxiosInstance
export function initializeAxios (axiosInstance: NuxtAxiosInstance) {
$axios = axiosInstance
}
let $cookies: NuxtCookies
export function initializeCookies (cookiesInstance: NuxtCookies) {
$cookies = cookiesInstance
}
export { $axios, $cookies }
plugin/axios-accessor.ts中:
import { Plugin } from '@nuxt/types'
import { AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios'
// 新增引入
import { initializeAxios, initializeCookies } from '~/utils/api'
const accessor: Plugin = ({ error, app: { $axios, $cookies } }) => {
// 此处调用
initializeAxios($axios)
initializeCookies($cookies)
$axios.onRequest((config: AxiosRequestConfig) => {
// ...
return config
})
$axios.onError((e: AxiosError) => {
// ...
})
// response拦截器,数据返回后,你可以先在这里进行一个简单的判断
$axios.interceptors.response.use((response: AxiosResponse) => {
const res = response
if (res.status === 200) {
return Promise.resolve(res)
} else {
return Promise.reject(res)
}
},
(e: any) => {
const { status, data } = e.response
error({ statusCode: status, message: data })
return Promise.reject(e)
})
}
在其他文件中,只需:import { $cookies } from '@/utils/api'
就可以直接使用啦!
OK,先写这么多,有问题欢迎指出交流。再次附上demo地址。