Nuxt.js 简介
- 随着工程量的不断增加,业务处理复杂度提高,传统架构的项目整体加载速度可能会越来越慢;与此同时,SPA 在内的组件化开发对 SEO 也非常不友好。
- 现在很多应用就开始使用 SSR 来解决这两个问题,但采用 SSR 在另一方面也给服务器增加了压力。
- Nuxt.js 便是一个支持 SSR 的前端框架,基于 Vue.js,通过对客户端 / 服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI 渲染。
官网:https://www.nuxtjs.cn/guide
创建 Nuxt 项目
安装
Nuxt.js 团队创建了脚手架工具 create-nuxt-app,这里直接使用 npx 安装。
期间会提示项目名称、UI 框架、Web 框架、SSR 模式还是单页面模式等的选择,根据自己的需要进行选择。
加载
等项目 build 完成,进入项目根目录下启动项目。
查看
启动默认端口为3000,在启动完成会给出主页的url,在浏览器输入:
目录结构
1 2 3 4 5 6 7 8 9 10
| .nuxt 打包的项目 assets 存放资源文件 (图片, 默认 CSS 代码等) components 组件文件 layouts 布局目录 middleware 中间件 pages 默认路由对应的页面 plugins 插件配置文件 static 静态文件 (也可以存放图片等资源) store Vuex 文件 nuxt.config.js 配置文件 (vue.config.js 相似)
|
Nuxt.js 使用
CSS 相关
全局引入
- 在 assets 目录下新建
css/global.css
文件,写入如下内容:1 2 3
| body { background-color: red; }
|
- 然后在
nuxt.config.js
的 css 下修改为下面配置:1 2 3
| css: [ '@/assets/css/global.css' ],
|
注意:Nuxt 团队给出了 nuxt.config.js
中 css 项的加载顺序,是按照 css 的扩展文件名来排序的,而不是单纯的只看前后顺序。
3. 运行项目,可以看到所有项目背景都为红色了。
路由过渡动画
Nuxt.js 使用 Vue.js 的组件来实现路由切换时的过渡动效。
修改上面建的 assets/css/global.css
文件,添加下面样式:
1 2 3 4 5 6
| .page-enter-active, .page-leave-active { transition: opacity .5s; } .page-enter, .page-leave-active { opacity: 0; }
|
再次点击跳转,便有了动画效果。
路由
Nuxt 默认会监听 pages
目录下的文件变化,新建 .vue
文件时会自动添加到路由中,路由模式便是文件的位置信息,可在 .nuxt/routes.json
中查看。
基础路由
pages
的目录结构:
1 2 3 4 5
| pages/ --| user/ -----| index.vue --| index.vue --| test.vue
|
routes.json
自动生成的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [ { name: 'index', path: '/', component: 'pages/index.vue' }, { name: 'test', path: '/test', component: 'pages/test.vue' }, { name: 'user', path: '/user', component: 'pages/user/index.vue' } ]
|
路由跳转
1 2 3
| <template> <nuxt-link to="/">首页</nuxt-link> </template>
|
动态路由
需要创建对应的以下划线作为前缀的 Vue 文件或目录:
1 2 3 4
| pages/ --| users/ -----| _id.vue --| index.vue
|
routes.json
自动生成的配置:
1 2 3 4 5 6 7 8 9 10 11 12
| [ { name: 'index', path: '/', component: 'pages/index.vue' }, { name: 'users-id', path: '/users/:id?', component: 'pages/users/_id.vue' } ]
|
users-id
的路由路径带有 :id?
参数,表示该路由是可选的,可在跳转时传递参数。
1 2 3
| <template> <nuxt-link to="/users/123">首页</nuxt-link> </template>
|
在 users/_id.vue
页面中获取参数:
1
| let param = this.$route.params.id;
|
嵌套路由
嵌套路由,可在页面中嵌套子页面,可用于 table 切换之类的场景。
1 2 3 4 5
| pages/ --| users/ -----| _id.vue -----| index.vue --| users.vue
|
routes.json
自动生成的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| [ { path: '/users', component: 'pages/users.vue', children: [ { path: '', component: 'pages/users/index.vue', name: 'users' }, { path: ':id', component: 'pages/users/_id.vue', name: 'users-id' } ] } ]
|
嵌套路由需在父容器中使用 nuxt-child 显示子页面,默认显示 users/index.vue
,切换子页面同样使用:nuxt-link 。
1
| <nuxt-child keep-alive :foobar="123"></nuxt-child>
|
中间件
中间件允许您定义一个自定义函数运行在一个页面或一组页面渲染之前,每一个中间件应放置在 middleware
目录下。
比如我可以利用中间件,来进行路由跳转时的验证:
- 新建
middleware/auth.js
文件,写入如下内容:
1 2 3 4
| export default function (context) { console.log("start"); context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent; }
|
- 在
nuxt.config.js
文件中添加:
1 2 3
| router: { middleware: 'auth' }
|
- 再次运行,便可看到每次打开页面都会打印日志。
布局
默认布局
可通过添加 layouts/default.vue
文件来扩展应用的默认布局。
但一定要添加显示页面的主体内容。
1 2 3 4 5 6
| <template> <div> <div>标题</div> <nuxt /> </div> </template>
|
错误页面
新建layouts/error.vue
文件,添加如下内容,样式可自己修改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <template> <div class="container"> <h1>404</h1> <h1 v-if="error.statusCode === 404">页面不存在</h1> <h1 v-else>应用发生错误异常</h1> <nuxt-link to="/">首 页</nuxt-link> </div> </template>
<script> export default { props: ['error'], layout: 'blog' } </script> <style> .container { width: 20%; margin: 50px auto; } </style>
|
异步数据
asyncData
asyncData 方法会在组件 (限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。
在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用 asyncData 方法来获取数据,Nuxt.js 会将 asyncData 返回的数据融合组件 data 方法返回的数据一并返回给当前组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <script> import axiox from 'axios'; export default { async asyncData({params}) { return axiox.get("http://localhost/GetData/" + params.id) .then(res => { console.log(res.data.title) return {title: res.data.title} }); }, data() { return { title: 'NG' } } } </script>
|
async / await
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script> import axiox from 'axios'; export default { async asyncData({params}) { const { data } = await axiox.get("http://localhost/GetData/" + params.id); console.log(data); return {title: data.title} }, data() { return { title: 'NG' } } } </script>
|
回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <script> import axiox from 'axios'; export default { asyncData({params},callback) { axiox.get("http://localhost/GetData/" + params.id) .then(res => { console.log(res.data.title) callback(null, { title: res.data.title }) }); }, data() { return { title: 'NG' } } } </script>
|