Nuxt官方文档
简单说,Nuxt
就是基于Vue
的一个应用框架,采用服务端渲染
,让你的SPA应用(Vue)也可以拥有SEO
Vue
的生命周期
全都跑在客户端
(浏览器),而Nuxt
的生命周期有些在服务端(Node),客户端,甚至两边都在:
生命周期流程图,红框内的是Nuxt的生命周期(运行在服务端)
,黄框内同时运行在服务端&&客户端上
,绿框内则运行在客户端
Nuxt.js-路由文档
Nuxt.js 依据 pages 目录
结构自动生成
vue-router 模块的路由配置。
要在页面之间使用路由,建议使用 标签。
<template>
<nuxt-link to="/">首页</nuxt-link>
</template>
假设 pages 的目录结构如下:
pages/
--| user/
-----| index.vue
-----| one.vue
--| index.vue
那么,Nuxt.js 自动生成的路由配置如下:
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'user',
path: '/user',
component: 'pages/user/index.vue'
},
{
name: 'user-one',
path: '/user/one',
component: 'pages/user/one.vue'
}
]
}
在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录
。
以下目录结构:
pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue
Nuxt.js 生成对应的路由配置表为:
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users-id',
path: '/users/:id?',
component: 'pages/users/_id.vue'
},
{
name: 'slug',
path: '/:slug',
component: 'pages/_slug/index.vue'
},
{
name: 'slug-comments',
path: '/:slug/comments',
component: 'pages/_slug/comments.vue'
}
]
}
你会发现名称为users-id
的路由路径带有 :id? 参数
,表示该路由是可选的
。如果你想将它设置为必选的路由,需要在 users/_id 目录内创建一个 index.vue 文件。
路由参数校验、嵌套路由、动态嵌套路由等等可以直接看官方文档,Nuxt.js-路由文档
asyncData方法
Nuxt.js 扩展了 Vue.js,增加了一个叫asyncData 的方法
,使得我们可以在设置组件的数据之前
能异步获取或处理数据。
asyncData
方法会在组件(限于页面组件
)每次加载之前
被调用
。它可以在服务端或路由更新之前被调用。
在这个方法被调用的时候,第一个参数
被设定为当前页面的上下文对象
,你可以利用 asyncData方法来获取数据
Nuxt.js 会将 asyncData 返回的数据融合
组件 data 方法返回的数据一并返回给当前组件
。
注意:由于
asyncData方法
是在组件初始化前
被调用的,所以在方法内是没有办法通过 this 来引用
组件的实例对象。
Nuxt.js 提供了几种不同的方法来使用 asyncData 方法,你可以选择自己熟悉的一种来用:
如果项目中直接使用了node_modules中的axios,并且使用axios.interceptors添加拦截器对请求或响应数据进行了处理,确保使用 axios.create创建实例后再使用。否则多次刷新页面请求服务器,服务端渲染会重复添加拦截器,导致数据处理错误。
import axios from 'axios'
const myaxios = axios.create({
// ...
})
myaxios.interceptors.response.use(function (response) {
return response.data
}, function (error) {
// ...
})
export default {
asyncData ({ params }) {
return axios.get(`https://my-api/posts/${params.id}`)
.then((res) => {
return { title: res.data.title }
})
}
}
export default {
async asyncData ({ params }) {
const { data } = await axios.get(`https://my-api/posts/${params.id}`)
return { title: data.title }
}
}
export default {
asyncData ({ params }, callback) {
axios.get(`https://my-api/posts/${params.id}`)
.then((res) => {
callback(null, { title: res.data.title })
})
}
}
如果组件的数据不需要异步获取或处理,可以直接返回指定的字面对象作为组件的数据。
export default {
data () {
return { foo: 'bar' }
}
}
asyncData 方法返回的数据在融合 data 方法返回的数据后,一并返回给模板进行展示,如:
<template>
<h1>{{ title }}</h1>
</template>
可通过 API context 来了解该对象的所有属性和方法。
在服务器端调用asyncData时,您可以访问用户请求的req和res对象。
export default {
async asyncData ({ req, res }) {
// 请检查您是否在服务器端
// 使用 req 和 res
if (process.server) {
return { host: req.headers.host }
}
return {}
}
}
Nuxt.js 在上下文对象context中提供了一个 error(params) 方法,你可以通过调用该方法来显示错误信息页面。params.statusCode 可用于指定服务端返回的请求状态码。
以返回 Promise 的方式举个例子:
export default {
asyncData ({ params, error }) {
return axios.get(`https://my-api/posts/${params.id}`)
.then((res) => {
return { title: res.data.title }
})
.catch((e) => {
error({ statusCode: 404, message: 'Post not found' })
})
}
}
如果你使用 回调函数 的方式, 你可以将错误的信息对象直接传给该回调函数, Nuxt.js 内部会自动调用 error 方法:
export default {
asyncData ({ params }, callback) {
axios.get(`https://my-api/posts/${params.id}`)
.then((res) => {
callback(null, { title: res.data.title })
})
.catch((e) => {
callback({ statusCode: 404, message: 'Post not found' })
})
}
}
Vuex状态树
对于每个大项目来说,使用状态树 (store) 管理状态 (state) 十分有必要。这就是为什么 Nuxt.js 内核实现了 Vuex。
Nuxt.js 会尝试找到应用根目录下的 store 目录
,如果该目录存在,它将做以下的事情:
Nuxt.js 支持两种使用 store 的方式,你可以择一使用:
无论使用那种模式,您的state的值
应该始终是function
,为了避免返回引用类型,会导致多个实例相互影响。
Nuxt.js允许您拥有一个 store 目录,其中包含与模块对应的每个文件。
首先,只需将状态导出为 函数,将变量和操作作为 store/index.js 中的对象导出:
export const state = () => ({
counter: 0
})
export const mutations = {
increment (state) {
state.counter++
}
}
然后,您可以拥有 store/todos.js 文件:
export const state = () => ({
list: []
})
export const mutations = {
add (state, text) {
state.list.push({
text,
done: false
})
},
remove (state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle (state, todo) {
todo.done = !todo.done
}
}
Vuex将如下创建
new Vuex.Store({
state: () => ({
counter: 0
}),
mutations: {
increment (state) {
state.counter++
}
},
modules: {
todos: {
namespaced: true,
state: () => ({
list: []
}),
mutations: {
add (state, { text }) {
state.list.push({
text,
done: false
})
},
remove (state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle (state, { todo }) {
todo.done = !todo.done
}
}
}
}
})
在您的 pages/todos.vue 中,使用 todos 模块:
<template>
<ul>
<li v-for="todo in todos">
<input type="checkbox" :checked="todo.done" @change="toggle(todo)">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
</li>
<li><input placeholder="What needs to be done?" @keyup.enter="addTodo"></li>
</ul>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
computed: {
todos () {
return this.$store.state.todos.list
}
},
methods: {
addTodo (e) {
this.$store.commit('todos/add', e.target.value)
e.target.value = ''
},
...mapMutations({
toggle: 'todos/toggle'
})
}
}
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
模块方法也适用于顶级定义,而无需在 store 目录中实现子目录
示例:您创建文件 store/state.js 并添加以下内容
export default () => ({
counter: 0
})
相应的可以在文件夹中添加 store/mutations.js
export default {
increment (state) {
state.counter++
}
}
您可以将模块文件分解为单独的文件:state.js,actions.js,mutations.js和getters.js。如果您使用index.js来维护state,getters,actions和mutations,同时具有单个单独的操作文件,那么仍然可以正确识别该文件。
注意:在使用拆分文件模块
时,必须记住使用箭头函数功能
, this 在词法上可用。词法范围this意味着它总是指向引用箭头函数的所有者。如果未包含箭头函数
,那么this将是未定义的(undefined)
。解决方案是使用 “normal” 功能,该功能会将this指向自己的作用域,因此可以使用。
fetch 方法会在渲染页面前被调用
,作用是填充状态树 (store) 数据
,与 asyncData 方法类似,不同的是fetch不会设置组件的数据
。
fetch-API文档
如果在状态树中指定了 nuxtServerInit 方法,Nuxt.js 调用它的时候会将页面的上下文对象
作为第2个参数
传给它(服务端调用时才会生效)。当我们想将服务端的一些数据传到客户端时,这个方法是灰常好用的。
举个例子,假设我们服务端的会话状态树里可以通过 req.session.user 来访问当前登录的用户。将该登录用户信息传给客户端的状态树,我们只需更新 store/index.js 如下:
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}
如果你使用_状态树模块化_的模式,只有主模块
(即 store/index.js)适用设置该方法(其他模块设置了也不会被调用)。
nuxtServerInit 方法接收的上下文对象和 fetch 的一样,但不包括 context.redirect() 和 context.error()。
注意:异步nuxtServerInit操作必须返回Promise来通知nuxt服务器等待它们。
actions: {
async nuxtServerInit({ dispatch }) {
await dispatch('core/load')
}
}
使用nuxt官网提供的脚手架
// nuxt-learn 是项目名
npx create-nuxt-app nuxt-learn
初始化的项目使用了nodemon监听和热刷新脚本,仅支持require语法,不支持es6的imoort语法
使用nodemon
可以监听文件修改,然后让服务器自行重启。
// package.json
"scripts": {
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
"build": "nuxt build",
"start": "cross-env NODE_ENV=production node server/index.js",
"generate": "nuxt generate"
},
// 正常
const Koa = require('koa')
// 改为import 报错
import Koa from 'koa'
使用 babel-node
可以在 node 端自行编译并运行
es6 甚至 es7。安装方法如下:
npm i @babel/core @babel/cli @babel/preset-env @babel/node -D
// 或者使用 yarn
注意:我这里是局部安装的,全局安装的方法请自行看官方文档。
然后我们需要在项目的根目录下面创建 .babelrc 文件
:
// .babelrc文件
{
"presets": ["@babel/preset-env"]
}
最后修改 package.json
// package.json文件 在dev和start后面加上--exec babel-node
"scripts": {
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server --exec babel-node",
"build": "nuxt build",
"start": "cross-env NODE_ENV=production node server/index.js --exec babel-node",
"generate": "nuxt generate"
},
说明一下为什么要加 --exec
这个参数:这个参数是让 nodemon 能运行非 node 程序
比如运行 py 文件nodemon --exec “python -v” ./app.py。在这里因为我们是用 nodemon 运行 babel-node,而不是 server.js,所以需要加 --exec 这个参数。
这样就支持import语法了,可以重新跑一下服务
npm run dev
// pages/index.vue
<style lang="scss">
</style>
不处理直接使用会报错
引入两个依赖包sass-loader和node-sass
npm install sass-loader
npm install node-sass
// 如果node-sass安装失败 可以尝试使用淘宝镜像安装
// 如果没有淘宝镜像 可以先安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install node-sass
安装好两个依赖包后,就能兼容sass语法了
vue-cli
入口文件是app.vue
,在nuxt
开发当中则是./layout/default.vue
<template>
<div id="app">
<!-- 公共头部组件 -->
<xxx-header></xxx-header>
<!-- 路由视图,相当于router-view -->
<nuxt/>
<!-- 公共底部组件 -->
<xxx-footer></xxx-footer>
</div>
</template>
验证码通过qq邮箱发送
QQ邮箱 设置 账户
得到一个授权码,需要写进配置文件里
import 引入的包可以通过
npm install 名字 去获取
server/dbs/config.js
export default {
// mongodb数据库地址 端口号默认 27017 student为数据组名称
dbs: 'mongodb://127.0.0.1:27017/student',
// redis 用来存验证码 效率比较高
redis: {
get host() {
return '127.0.0.1'
},
get port() {
// 默认端口号
return 6379
}
},
// smtp服务 发验证码邮件
smtp: {
get host() {
// 腾讯邮箱
return 'smtp.qq.com'
},
get user() {
return '[email protected]'
},
// 通过qq邮箱设置 得到的授权码
get pass() {
return 'ersetxsjtpuxijae'
},
get code() {
return () => {
// 随机生成四位验证码
return Math.random().toString(16).slice(2, 6).toUpperCase()
}
},
get expire() {
// 过期时间 1分钟
return ()=> {
return new Date().getTime() + 60 * 60 * 1000
}
}
}
}
server/dbs/models/users.js
import mongoose from 'mongoose'
const Schema = mongoose.Schema
const UserSchema = new Schema({
username: {
type: String,
// true表示唯一
unique: true,
// 必填
require: true
},
password: {
type: String,
require: true
},
email: {
type: String,
require: true
}
})
export default mongoose.model('User', UserSchema)
server\interface\utils\axios.js
简单封装axios
import axios from 'axios'
const instance = axios.create({
baseURL: `http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}`,
// 超时
timeout: 1000,
// 默认头部
headers: {
}
})
export default instance
server\interface\utils\passport.js
用来验证用户密码
import passport from 'koa-passport'
import LocalStrategy from 'passport-local'
import UserModel from '../../dbs/models/users'
passport.use(new LocalStrategy(async (username, password, done) => {
let where = {
username
}
let result = await UserModel.findOne(where)
if (result != null) {
if (result.password === password) {
// 用户输入密码跟数据库密码一致
return done(null, result)
} else {
return done(null, false, '密码错误')
}
} else {
return done(null, false, '用户不存在')
}
}))
// 用户每次进来 自动通过session验证
// 在每次请求时 会从session中读取用户对象 用户通过验证后serializeUser会将用户数据存在session中
// 序列化
passport.serializeUser((user, done) => {
done(null, user)
})
// 反序列化
passport.deserializeUser((user, done) => {
done(null, user)
})
export default passport
server\interface\users.js
users下相关接口实现
import Router from 'koa-router'
import Redis from 'koa-redis'
// nodemailer支持node发邮件
import nodeMailer from 'nodemailer'
import User from '../dbs/models/users'
import Passport from './utils/passport'
import Email from '../dbs/config'
import axios from './utils/axios'
// 路由前缀
let router = new Router({
prefix: '/users'
})
// 获取redis客户端
let Store = new Redis().client
// 注册接口
router.post('/signup', async(ctx) => {
const {
username,
password,
email,
code
} = ctx.request.body
// 校验验证码 nodemailer发验证码时会存进redis里 这里从redis里拿出对比
if (code) {
// Store.hget(`nodemail:${username}`, 'code') redis是key-value存储 nodemail表示属于哪个模块 username用来匹配 减值code
const saveCode =await Store.hget(`nodemail:${username}`, 'code')
// 过期时间
const saveExpire = await Store.hget(`nodemail:${username}`, 'expire')
if (code === saveCode) {
if (new Date().getTime() - saveExpire > 0) {
ctx.body = {
code: -1,
msg: '验证码已过期,请重新尝试'
}
return false
}
} else {
ctx.body = {
code: -1,
msgL: '请填写正确的验证码'
}
}
} else {
ctx.body = {
code: -1,
msg:'请填写验证码'
}
}
let user = await User.find({
username
})
if (user.length) {
ctx.body = {
code: -1,
msg: '已被注册'
}
return
}
// 写库操作
let nuser = await User.create({
username,
password,
email
})
if (nuser) {
// 写库成功
let res = await axios.post('/users/signin', {
username,
password
})
if (res.data && res.data.code ===0) {
ctx.body = {
code: 0,
msg: '注册成功',
user: res.data.user
}
} else {
ctx.body = {
code: -1,
msg: 'error'
}
}
} else {
ctx.body = {
code: -1,
msg: '注册失败'
}
}
})
// 登录接口
router.post('/signin', async (ctx, next) => {
return Passport.authenticate('local', function(err, user, info, status) {
if (err) {
ctx.body = {
code: -1,
msg: err
}
} else {
if (user) {
ctx.body = {
code: 0,
msg: '登录成功',
user
}
return ctx.login(user)
} else {
// 异常
ctx.body = {
code: 1,
msg: info
}
}
}
})(ctx, next)
})
// 验证码验证
router.post('/verify', async (ctx, next) => {
let username = ctx.request.body.username
const saveExpire = await Store.hget(`nodemail:${username}`, 'expire')
if (saveExpire && new Date().getTime() - saveExpire > 0) {
ctx.body = {
code: -1,
msg: '验证请求过于频繁,1分钟内1次'
}
return false
}
// 验证邮件相关
// 发送对象
let transporter = nodeMailer.createTransport({
host: Email.smtp.host,
port: 587,
// secure: true 则监听405端口 false 为其他端口
secure: false,
// 权限校验
auth: {
user: Email.smtp.user,
pass: Email.sntp.pass
}
})
// 接手对象
let ko = {
code:Email.smtp.code(),
expire:Email.smtp.expire(),
email: ctx.request.body.email,
user: ctx.request.body.username
}
// 邮件显示内容
let mailOptions = {
// 标题
from: `"认证邮件" <${Email.smtp.user}>`,
to: ko.email,
// 主题
subject: '《慕课网高仿美团网全栈实战》注册码',
html: `您在《慕课网高仿美团网全栈实战》课程中注册,您的邀请码是&{ko.code}`
}
// 发送邮件
await transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log('error')
} else {
// 存到redis哈希表里
Store.hmset(`nodemail:${ko.user}`, 'code', ko.code, 'expire', ko.expire, 'email', ko.email)
}
})
ctx.body = {
code: 0,
msg: '验证码已发送,可能会有延时,有效期1分钟'
}
})
// 退出接口
router.get('/exit', async (ctx, next) => {
await ctx.logout()
// isAuthenticated 这个API由passport包提供
if (!ctx.isAuthenticated()) {
// 检查当前是不是登录状态 不是的话 说明退出成功
ctx.body = {
code:0
}
} else {
ctx.body = {
code: -1
}
}
})
// 获取用户名
router.get('/getUser', async (ctx) => {
// isAuthenticated 这个API由passport包提供 user也是登录成功时passport这个包存进session里的
if (ctx.isAuthenticated()) {
const {username, email} = ctx.session.passport.user
ctx.body = {
user: username,
email
}
} else {
ctx.body = {
user: '',
email: ''
}
}
})
// 导出路由
export default router
server\index.js
引入相关包,配置
// const Koa = require('koa')
import Koa from 'koa'
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
import mongoose from 'mongoose'
// 用来处理post请求相关 没有这个包就无法通过ctx.request.body获取post请求参数
import bodyParser from 'koa-bodyparser'
// 存session cookie相关的 包
import session from 'koa-generic-session'
import Redis from 'koa-redis'
// 解决服务端向客户端发json 格式美化
import json from 'koa-json'
// 数据库相关配置
import dbConfig from '../server/dbs/config'
import passport from './interface/utils/passport'
import users from '../server/interface/users'
const app = new Koa()
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
config.dev = app.env !== 'production'
async function start () {
// Instantiate nuxt.js
const nuxt = new Nuxt(config)
const {
host = process.env.HOST || '127.0.0.1',
port = process.env.PORT || 3000
} = nuxt.options.server
app.keys = ['mt', 'keyskeys']
app.proxy = true
// 客户端存的是cookie 服务端是session
app.use(session({
key: 'mt',
prefix: 'mt:uid',
// session 相关存到redis
store: new Redis()
}))
app.use(bodyParser({
extendTypes: ['json', 'form', 'text']
}))
app.use(json())
// 连接数据库
mongoose.connect(dbConfig.dbs, {
useNewUrlParser: true
})
// 处理登录相关
app.use(passport.initialize())
app.use(passport.session())
await nuxt.ready()
// Build in development
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
}
// 引入路由
app.use(users.routes()).use(users.allowedMethods())
app.use((ctx) => {
ctx.status = 200
ctx.respond = false // Bypass Koa's built-in response handling
ctx.req.ctx = ctx // This might be useful later on, e.g. in nuxtServerInit or with nuxt-stash
nuxt.render(ctx.req, ctx.res)
})
app.listen(port, host)
consola.ready({
message: `Server listening on http://${host}:${port}`,
badge: true
})
}
start()
启动redis服务
redis-server
mongo
// 或者 看你的mongo名称
mongod
跑一下项目服务
npm run dev
server\interface\geo.js
import Router from "koa-router";
import axios from "./utils/axios";
// 路由前缀
let router = new Router({
prefix: "/geo"
});
const sign = 'abcd'
router.get('/getPosition', async (ctx) => {
let {
status,
data: {
province,
city
}
} = await axios.get(`http://cp-tools.cn/geo/getPosition?sign=${sign}`)
if (status === 200) {
ctx.body = {
province,
city
}
} else {
ctx.body={
province: '',
city: ''
}
}
})
export default router
server\index.js
导入路由
import users from '../server/interface/users'
import geo from '../server/interface/geo'
app.use(users.routes()).use(users.allowedMethods())
app.use(geo.routes()).use(geo.allowedMethods())
通过nuxtServerInit方法实现ssr渲染获取到的定位
store\modults\geo.js
const state = () => {
position: {}
}
const mutations = {
setPosition(state, val) {
console.log('geo mutations val:')
console.log(val)
state.position = val
}
}
const actions = {
setPosition: ({
commit
}, position) => {
commit('setPosition', position)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
store\index.js
import Vue from 'vue'
import Vuex from 'vuex'
import geo from './modults/geo'
Vue.use(Vuex)
const store = () => new Vuex.Store({
modules: {
geo
},
actions: {
async nuxtServerInit({
commit
}, {req, app}) {
console.log('nuxtServerInit:')
const {status, data: {province, city}} = await app.$axios.get('/geo/getPosition')
console.log(province, city)
// 这里的检查是在客户端做的
commit('geo/setPosition', status === 200 ? {city, province} : {province:'', city: ''})
}
}
})
export default store
前端页面
components\public\header\geo.vue
// 获取到服务端存放在vuex的定位
{{$store.state.geo.position.city}}
server\dbs\models\menu.js
import mongoose from 'mongoose'
const Schema = mongoose.Schema
const Menu = new Schema({
menu: {
type: Array,
require: true
}
})
export default mongoose.model('Menu', Menu)
server\interface\geo.js
import Router from "koa-router";
import axios from "./utils/axios";
import Menu from '../dbs/models/menu'
import Proviece from '../dbs/models/province'
// 路由前缀
let router = new Router({
prefix: "/geo"
});
const sign = 'abcd'
router.get('/getPosition', async (ctx) => {
let {
status,
data: {
province,
city
}
} = await axios.get(`http://cp-tools.cn/geo/getPosition?sign=${sign}`)
if (status === 200) {
ctx.body = {
province,
city
}
} else {
ctx.body={
province: '',
city: ''
}
}
})
router.get('/getMenu', async (ctx) => {
// 数据库操作
const result = await Menu.findOne()
ctx.body = {
menu: result.menu || []
}
// 线上接口
// let {status, data: {menu}} = await axios.get(`http://cp-tlls.cn/geo/menu?sign=${sign}`)
// if (status = 200) {
// ctx.body = {
// menu: munu
// }
// } else {
// ctx.body = {
// menu: []
// }
// }
})
export default router
store\modults\home.js
const state = () => ({
menu: []
})
const mutations = {
setMenu(state, val) {
state.menu = val
}
}
const actions = {
setMenu: ({
commit
}, menu) => {
commit('setMenu', menu)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
store\index.js
import Vue from 'vue'
import Vuex from 'vuex'
import geo from './modults/geo'
import home from './modults/home'
Vue.use(Vuex)
const store = () => new Vuex.Store({
modules: {
geo,
home
},
actions: {
async nuxtServerInit({
commit
}, {req, app}) {
console.log('nuxtServerInit:')
// geo
const {status, data: {province, city}} = await app.$axios.get('/geo/getPosition')
commit('geo/setPosition', status === 200 ? {city, province} : {province:'', city: ''})
// home
const {status:status2,data: {menu}} = await app.$axios.get('/geo/getMenu')
commit('home/setMenu', status2 === 200 ? menu : [])
}
}
})
export default store
前端页面通过
// 获取menu值
this.$store.state.home.menu
谢谢你阅读到了最后
期待你,点赞、评论、交流