nuxt从零搭建登录鉴权asyncData异步数据
- nuxt_ehr
- 初始化项目
- 创建路由
- 创建全局样式文件
- 创建全局菜单
- 鉴权逻辑
- 登录登出逻辑
- 页面组件 asyncData 获取异步数据
- 改写loading样式
- 改写error页面
- 代码
nuxt_ehr
初始化项目
npx create-nuxt-app nuxt_ehr
npm run dev
运行 http://localhost:3000/
创建路由
pages
目录结构自动生成模块的路由配置,更复杂的路由配置可以查看路由文档
- 清空
pages/index.vue
内容,并创建pages/info.vue
文件(随便写点内容此时一下路由显示)
当前结果:此时可以手动切换 /
和 /info
两个路径
下一步:创建全局样式文件
创建全局样式文件
- 创建样式文件
assets/css/common.less
-
nuxt.config.js
配置文件中引入全局样式内容css: ['@/assets/css/common.less']
- 安装依赖
npm i less-loader@6
nuxt.config.js
配置less-loader
build: {
loaders: {
less: {
lessOptions: {
javascriptEnabled: true
}
}
}
}
- 创建
assets/css/vars.less
,改变主题颜色,同时增加主题颜色样式选择器(引入组件库的.less
样式文件并覆盖其主题变量) -
npm i @nuxtjs/style-resources
(vars.less
文件中定义了用于覆盖主题变量的@primary-color
,如果页面组件中想要用这个变量需要@import
这个文件,而 @nuxtjs/style-resources 这个库就解决了这个麻烦的步骤,无需@import
就可以直接读取变量作为全局变量使用) nuxt.config.js
文件增加配置内容
buildModules: [
'@nuxtjs/style-resources'
],
styleResources: {
less: '@/assets/css/vars.less'
},
更多样式配置可以查看The css property 更多关于 buildModules 和 modules 的配置以及不同点可以查看 Modules directory
当前结果:可以在 common.less
中添加全局样式内容,在 vars.less
中定义的样式变量或者覆盖组件库默认主题变量,在页面组件 style
中可以直接使用这些变量
下一步:提取全局菜单结构,并可以通过菜单切换路由显示
创建全局菜单
菜单属于公共部分,路由切换不会改变菜单内容(除了样式变化)
- 程序的默认布局是
layouts/default.vue
(如果不修改可以没有这个文件),可通过添加layouts/default.vue
文件来扩展应用的默认布局(别忘了在布局文件中添加<Nuxt/>
组件用于显示页面的主体内容,即<Nuxt />
才是显示页面组件内容的位置)layouts
目录中的每个文件 (顶级) 都将创建一个可通过页面组件中(pages
下组件)的layout
属性访问的自定义布局(不指定就是默认布局default
)components
文件夹中的组件会自动注册成全局组件
- 创建
layouts/default.vue
布局文件,并修改内容(插入全局菜单组件) - 清空
components
下的所有全局组件内容 - 创建全局菜单组件
components/app-header.vue
文件
当前结果:访问 /
可以看到 components/app-header.vue
和 pages/index.vue
内容的显示
下一步:登录获取当前登录名以及菜单内容
鉴权逻辑
token校验 && 状态持久化思路:
登录时,同步 vuex && cookie,强制刷新后,nextServerInit 取出 cookie,并同步 vuex, axios 拦截去读取 vuex。
store
文件夹下新建文件,nuxt 就会自动导入 Vuex,且添加store
选项到 vue 实例上nuxtServerInit
可以接收服务端的一些数据(如登录信息),从而将其保存在状态管理中,客户端就可以从状态管理中去获取- 只有主模块(
store/index.js
) 才能接收nuxtServerInit
action
- 创建状态管理主模块
store/index.js
(此时auth.js
函数中自动多了一个状态树参数store
)并通过nuxtServerInit
来获取并保存当前登录信息到状态管理树中 - 创建用户信息状态管理文件
store/user.js
(通过store.state.user.xxx
来获取对应的状态值) - 创建鉴权中间件
middleware/auth.js
,auth.js
的判断逻辑为当前用户是否登录(store.state.user.token
是否有值),没登录需要跳转至登录页 -
nuxt.config.js
配置router: {middleware: 'auth'}
,每次路由变化都会经过鉴权判断是否登录 - 创建登录页面
pages/login.vue
nuxt 有三个地方可以设置中间件,也可以设置异步中间件,路由中间件 will be called for every route change,关于中间件更多详细设置可以查看 middleware nuxt中配置store可以查看Store directory
当前结果:因为一直没有登录,所以 token 一直是空,会一直在登录页面
下一步:完成接口请求配置,实现登录保存用户信息进入首页
登录登出逻辑
- 使用node创建一个本地服务器(
server
为服务器内容)模拟后端,用于登录请求或后端数据获取 -
npm i @nuxtjs/axios
并在nuxt.config.js
中配置modules: ['@nuxtjs/axios']
(此时在页面组件中可以通过this.$axios.xxx('/api/kkk')
发送请求了) npm i @nuxtjs/proxy
(由于mock的服务器端口跟nuxt项目端口不同,此时请求数据会有跨域问题),在nuxt.config.js
中配置
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
axios: {
proxy: true,
credential: true
},
proxy: {
'/api/': {
target: 'http://localhost:3333/',
pathRewrite: {
'^/api/': '/',
changeOrigin: true
}
}
}
- 拦截请求统一处理,创建处理文件
plugins/request.js
并在nuxt.config.js
中配置plugins: [..., '@/plugins/request']
-
npm i cookie-universal-nuxt
并在nuxt.config.js
的modules
中加入配置,使得上下文中可以获取到$cookie
- 登录成功后存储用户信息到 cookie 和 vuex 中
- 退出登录时候清除cookie 和 vuex的值
页面组件 asyncData 获取异步数据
asyncData
方法会在组件(限于页面组件)每次加载之前被调用,也因为如此,在该方法内是没有办法通过this
来引用组件的实例对象的- Nuxt.js 会将
asyncData
返回的数据融合组件data
方法返回的数据一并返回给当前组件
// pages/index.vue
data() {
return {
}
},
async asyncData({$axios}) {
const { result } = await $axios.get('/api/home/userinfo')
let _userInfo = [
{label: '姓名:', key: 'name', value: ''},
{label: '部门:', key: 'apartment', value: ''},
{label: '岗位级别:', key: 'level', value: ''},
{label: '名片岗位:', key: 'business', value: ''},
{label: '直接上级:', key: 'supervisor', value: ''},
{label: '入职日期:', key: 'start', value: ''}
]
for(let key in result.user_info) {
const _idx = _userInfo.findIndex(item => item.key === key)
_userInfo[_idx].value = result.user_info[key]
}
return {
userPhoto: result.user_photo,
userInfo: _userInfo
}
},
更多使用方法和配置可以查看异步数据 asyncData
改写loading样式
默认 loading 是头部黑色进度条的样式,下面重写 loading 样式
- loading 组件需要遵循给定约定,即
start
为开始的样式,finish
为结束时的样式
- 创建
components/loading.vue
文件 -
nuxt.config.js
配置loading: '@/components/loading'
改写error页面
- 创建
layouts/error.vue
文件,传入约定式参数props: ['error']
代码