初识
- Nuxt.js 一个完整的服务器端请求到渲染的流程

配置SEO
- ssr主要是为了seo,我们可以统一为所有页面配置对应的title,description,也可以单独为每一个页面自定义配置
- 统一为所有页面配置可以在nuxt.config.js文件中配置如下:
head: {
title: '我们想要配置的标题',
meta: [
{ charset: 'utf-8' },
{ hid: 'description', name: 'description', content: process.env.npm_package_description || '' },
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
上面代码中的npm_package_description,事实上是在package.json里面增加如下配置
"description": "携程旅行网是中国领先的在线旅行服务公司,向超过9000万会员提供酒店预订、酒店点评及特价酒店查询、机票预订、飞机票查询、时刻表、票价查询、航班查询、度假预订、商旅管理、为您的出行提供全方位旅行服务。",
- 单独为某一个页面配置的话,可以在页面对应的vue文件里面增加如下配置:
head() {
return {
title: '自定义标题',
meta: [
{ name: 'description', hid: 'description', content: 'set page desc' }
],
link: [{ rel: 'favicon', href: 'favicon.ico' }]
}
},
配置路由
- 在pages文件夹下新建一个页面程序就会生成对应的路由
- 可以在.nuxt/router.js 这个文件里面看到自动生成的路由选项
- layouts文件夹里面一般会放一些模板文件,如果页面使用模板,可如下设置:
export default {
layout: 'blank'// blank为模板文件的名称
}
- 我们可以在模板文件里面配置路由,如下代码所示:
<template>
<div>
<nuxt-link to="/">首页</nuxt-link>
<NLink to="/admin">管理</NLink>
<n-link no-prefetch to="/cart">购物车</n-link>
<nuxt />
</div>
</template>
-
nuxt-link的别名可以为:n-link,NLink,NuxtLink
-
默认nuxt.js会启用prefetch在页面空闲的时候预加载其它路由数据,在路由上配置no-prefetch则会禁用预加载
-
如果要定义动态路由,以下划线作为前缀的 .vue文件或目录会被定义为动态路由,如下所示

-
如果要配置嵌套路由

异步数据获取
- 因为是服务器端渲染,所以要准备服务接口
- 首页安装
npm i koa koa-router koa-bodyparser -S
- 在根目录下创建server文件夹,并新建api.js,在此文件夹下创建mock接口,并启动mock接口 node server/api
const Koa = require('koa');
const app = new Koa();
const bodyparser = require("koa-bodyparser");
// 配置所有接口的请求前缀是api
const router = require("koa-router")({ prefix: "/api" });
// 设置cookie加密秘钥
app.keys = ["some secret", "another secret"];
// 一些mock 数据
const goods = [
{ id: 1, text: "连衣裙", price: 580 }, { id: 2, text: "衬衣", price: 320 },{ id: 3, text: "睡裙", price: 260 }
];
router.get("/goods", ctx => {
ctx.body = {
ok: 1,
goods
};
});
router.get("/detail", ctx => {
ctx.body = {
ok: 1,
data: goods.find(good => good.id == ctx.query.id)
};
});
router.post("/login", ctx => {
const user = ctx.request.body;
if (user.username === "admin" && user.password === "123456") {
// 将token存入cookie
const token = 'a mock token';
ctx.cookies.set('token', token, {
httpOnly: false ,
expires:new Date('2029-2-12'), // cookie失效时间
maxAge:1000*60*60*24,
});
ctx.body = { ok: 1, token };
} else {
ctx.body = { ok: 0 };
}
});
// 解析post数据并注册路由
app.use(bodyparser());
app.use(router.routes());
app.listen(8080, () => console.log('服务已启动'))
- 安装axios库
npm install @nuxtjs/axios -S
- 配置axios,使之成为nuxt模块并可用,在nuxt.config.js配置如下(所有修改nuxt.config.js都需要重启之后才能生效)
modules: [
'@nuxtjs/axios',
],
axios: {
proxy: true
},
proxy: {
"/api": "http://localhost:8080"
},
- 使用
async asyncData({ $axios, error }) {
// 运行时间是在组件创建前,这时候this是不能用的
const { ok, goods } = await $axios.$get('/api/goods')
if (ok) {
return { goods }
}
// 错误处理 重定向到错误页面
error({ statusCode: 400, message: '数据查询失败' })
},
async Data的一些注意事项,官网上说的很清晰:

- 常见的需求,有些页面需要权限控制,这个时候中间键就会起作用了
- 比方说在middleware文件夹下创建auth,示例代码如下:
export default function ({ route, redirect, store }) {
// 上下文中通过store访问vuex中的全局状态
// 通过vuex中令牌存在与否判断是否登录
if (!store.state.user.token) {
redirect("/login?redirect=" + route.path);
}
}
- 使用时可以通过单独页面使用,也可以统一使用
- 如果是统一使用的话,则可以在nuxt.config.js配置如下
router:{
middleware:[auth]
},
- 如果只需要对某几个页面配置的话,则可以在具体页面中使用
export default {
middleware: ['auth']
}
状态管理
- 在Nuxt.js根目录下会有store目录,在此目录建立文件,并具名导出state, mutations, getters, actions即可
- 比方说,我在store目录下建立user.js,示例代码如下所示:
export const state = () => ({
token: ''
});
export const mutations = {
SET_TOKEN (state, token) {
state.token = token;
}
};
export const getters = {
isLogin (state) {
return !!state.token;
}
};
export const actions = {
login ({ commit, getters }, u) {
// 利用nuxt提供inject注入了$login
// this指向的是当前vue的实例
return this.$login(u).then(({ token }) => {
if (token) {
commit("SET_TOKEN", token);
}
return getters.isLogin;
});
}
};
- 解释一下上面示例中this.$login方法是通过插件注入的
- 就以this.$login来说,在plugin文件夹下创建api-inject.js
export default ({ $axios }, inject) => {
inject("login", user => {
return $axios.$post("/api/login", user);
});
};
- 创建了login方法还只是其中一步,还需要在nuxt.config.js中配置
plugins: [
'@/plugins/api-inject',
],
- 一般来说,添加请求拦截器,附加token,都可以使用plugin来实现,示例代码如下所示:
export default function ({ $axios, store }) {
// onRequest是$axios模块提供的帮助文档
$axios.onRequest(config => {
if (store.state.user.token) {
config.headers.Authorization = "Bearer " + store.state.user.token;
}
return config;
});
}
登录后下次刷新还能保留登录状态
- 安装依赖模块:cookie-universal-nuxt
npm i -S cookie-universal-nuxt
- 配置 nuxt.config.js模块
modules: [
"cookie-universal-nuxt",
],
- store的根模块中定义 nuxtServerInit 方法,将服务端的一些数据传到客户端
export const actions = {
// nuxtServerInit必须声明在根模块当中
// 参数一是action上下文 参数二是组件上下文
nuxtServerInit ({ commit }, { app }) {
const token = app.$cookies.get("token");
if (token) {
commit("user/SET_TOKEN", token);
}
}
};
配置雪碧图
- 因为我这边css用的是scss,安装对应的loader
npm install -D sass-loader node-sass
- 自动把小图标合成雪碧图使用webpack-spritesmith
npm install --save-dev webpack-spritesmith
- 在nuxt.config.js文件中配置
build: {
extractCSS: { allChunks: true },
/*
** You can extend webpack config here
*/
extend (config, ctx) {
//如果是开发环境而且在客户端中执行
if (ctx.isDev && ctx.isClient) {
// 雪碧图插件
let path = require('path');
let SpritesmithPlugin = require('webpack-spritesmith');
// 雪碧图处理模板
let templateFunction = function (data) {
let shared = '.icon { display:inline-block; background-image: url(I); background-size:WSMpx HSMpx; }'
.replace('I', data.sprites[0].image)
.replace('WSM', data.spritesheet.width)
.replace('HSM', data.spritesheet.height);
let perSprite = data.sprites.map(function (sprite) {
return '.icon-N { width: Wpx; height: Hpx; background-position: Xpx Ypx; }'
.replace('N', sprite.name)
.replace('W', sprite.width)
.replace('H', sprite.height)
.replace('X', sprite.offset_x)
.replace('Y', sprite.offset_y);
}).join('\n');
return shared + '\n' + perSprite;
};
// 雪碧图扩展webpack配置
config.resolve.modules.push('./assets/img'); //css在哪里能找到sprite图
config.plugins.push(
new SpritesmithPlugin({
src: {
cwd: path.resolve(__dirname, './assets/img/spr/'), // 图标根路径
glob: '**/*.png' // 匹配任意 png 图标
},
target: {
image: path.resolve(__dirname, './assets/img/spr.png'), // 生成雪碧图目标路径与名称
// 设置生成CSS背景及其定位的文件或方式
css: [
[path.resolve(__dirname, './assets/scss/spr.scss'), {
format: 'function_based_template'
}]
]
},
customTemplates: {
'function_based_template': templateFunction,
},
apiOptions: {
cssImageRef: "~assets/img/spr.png", // css文件中引用雪碧图的相对位置路径配置
},
spritesmithOptions: {
padding: 10,
}
})
)
}
}
}
- 使用:
- 在 assets>img 目录下新建 spr 文件夹,把要用到的图标都放到此文件夹里面
- 页面上使用时,引入对应的css
<style lang="scss">
@import '../assets/scss/spr.scss'; //引入方式
</style>
- 使用图标很简单,图标的类名跟图标的文件名一致就行了,示例代码如下所示:
<i class="icon icon-huawei_hover"></i>
示例源码可见:git hub 源码
具体配置可见官网 Nuxt.js官网
最后
如果你觉得这篇文章不错,请别忘记点个赞跟关注哦~😊