Nuxt.js 学习
Nuxt.js 学习
📚 Vue 学习目录
🚀 Vue.js基础学习 - 📝 Vue.js进阶 - 🔦 webpack学习
📦 Vue-CLI学习 - 📌 Vue-router学习 - 🔮 Vuex学习 - 🎀 Nuxt.js 学习
在学习Nuxt.js之前、我们要知道什么是客户端渲染(SPA)
和服务端渲染(SSR)
客户端渲染和服务端渲染
客户端渲染 (SPA:single page application): 用户通过地址栏或者链接标签进入一个新的链接后,向服务器
发出请求
,服务器直接根据链接返回一个html页面(没有数据)
,页面中的数据渲染则是由页面中的ajax完成
,ajax再次向服务器发出请求数据的请求
,然后对页面进行渲染
优点
:前后端分离,开发效率高。
用户体验更好,我们将网站做成SPA(单页面应用)或者部分内容做成SPA,当用户点击时,不会形成频繁的跳转。
缺点:
前端响应速度慢,特别是首屏,这样用户是受不了的。
不利于SEO优化,因为爬虫不认识SPA,所以它只是记录了一个页面。
服务端渲染 (SSR:server side netdering): 用户通过地址栏或者链接进入一个服务器所监听的服务器的路径,服务器则根据
该路径返回一个页面(有数据)
,页面的数据渲染在服务器内由服务器完成,客户端只需要发送一次请求
,不用ajax
优点:
- 尽量不占用前端的资源,前端这块耗时少,速度快。
- 有利于SEO优化,因为在后端有完整的html页面,所以爬虫更容易爬取信息。
缺点:
- 不利于前后端分离,开发的效率降低了。
- 对html的解析,对前端来说加快了速度,但是加大了服务器的压力。
Vue 服务端渲染
通过npm init
初始化一个项目
npm安装
1 | npm install vue vue-server-netderer --save |
渲染一个 Vue 实例
index.js
1 | // 第 1 步:创建一个 Vue 实例 |
通过node index.js
可以看到、直接将template中的模板渲染成了html<div data-server-netdered="true">Hello world</div>
元素
与服务器集成
index.js
1 | const Vue = require('vue') |
查看源代码我们可以看的、页面已经渲染成了HTML标签
Nuxt.js
下图阐述了 Nuxt.js 应用一个完整的服务器请求到渲染(或用户通过 <nuxt-link>
切换路由渲染页面)的流程:
Nuxt.js 是什么?
Nuxt.js 是一个基于 Vue.js 的通用应用框架。
通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI 渲染。
我们的目标是创建一个灵活的应用框架,你可以基于它初始化新项目的基础结构代码,或者在已有 Node.js 项目中使用 Nuxt.js。
Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置。
除此之外,我们还提供了一种命令叫:nuxt generate
,为基于 Vue.js 的应用提供生成对应的静态站点的功能。
我们相信这个命令所提供的功能,是向开发集成各种微服务(Microservices)的 Web 应用迈开的新一步。
作为框架,Nuxt.js 为 客户端/服务端
这种典型的应用架构模式提供了许多有用的特性,例如异步数据加载、中间件支持、布局支持等。
安装
Nuxt.js 团队创建了脚手架工具 create-nuxt-app
1 | npx create-nuxt-app <项目名> |
解释一下npx
:
http://www.ruanyifeng.com/blog/2019/02/npx.html
这个是在 npmv5.2.0
引入的一条命令(查看),引入这个命令的目的是为了提升开发者使用包内提供的命令行工具的体验。
可以通过npx 调用项目安装的模块
1
2
3
4
5# 项目的根目录下执行
$ node-modules/.bin/mocha --version
# npx 调用
$ npx mocha --versioncreate-nuxt-app
这个模块是全局安装,npx 可以运行它,而且不进行全局安装。npx 将create-nuxt-app
下载到一个临时目录,使用以后再删除。所以,以后再次执行上面的命令,会重新下载create-nuxt-app
。
npx命令找包顺序:先自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你临时安装,执行完后再删除包。
它会让你进行一些选择:
项目名称
Project name:
直接回车程序语言
Programming language: (Use arrow keys):
JavaScript和TypeScript
、选择JavaScript
包管理工具
Package manager: (Use arrow keys):
Yarn和NPM
、选择NPM
UI框架
UI framework: (Use arrow keys)
:None (无) Bootstrap Vuetify BulmaTailwind Element UI Ant Design Vue Buefy iView Tachyons模块
Nuxt.js modules
:Axios和Progressive Web App (PWA)和Content
选择Axios
在保存时代码规范和错误检查您的代码Linting tools:
ESLint、Prettier、Lint staged files、StyleLint
测试框架
Testing framework
:None Jest AVA WebdriverIO
渲染模式
netdering mode
Universal (SSR / SSG)
Single Page AppDeployment target
Server (Node.js hosting)
Static (Static/JAMStack hosting)
Development tools
:jsconfig.json (Recommended for VS Code if you’re not using typescript)
Semantic Pull Requests
当运行完时,它将安装所有依赖项,因此下一步是启动项目:
1 | $ cd <project-name> |
应用现在运行在 http://localhost:3000 上运行。
注意:Nuxt.js 会监听 pages 目录中的文件更改,因此在添加新页面时无需重新启动应用程序。
目录结构
1 | ├── assets 资源目录 |
资源目录
assets
用于组织未编译的静态资源如LESS
、SASS
或JavaScript
。组件目录
components
用于组织应用的 Vue.js 组件。Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像页面组件那样有asyncData
方法的特性。布局目录
layouts
用于组织应用的布局组件。middleware
目录用于存放应用的中间件。页面目录
pages
用于组织应用的路由及视图。Nuxt.js 框架读取该目录下所有的.vue
文件并自动生成对应的路由配置。插件目录
plugins
用于组织那些需要在根vue.js应用
实例化之前需要运行的 Javascript 插件。静态文件目录
static
用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。服务器启动的时候,该目录下的文件会映射至应用的根路径/
下。举个例子:
/static/robots.txt
映射至/robots.txt
store
目录用于组织应用的 Vuex 状态树 文件。 Nuxt.js 框架集成了 Vuex 状态树 的相关功能配置,在store
目录下创建一个index.js
文件可激活这些配置。nuxt.config.js
文件用于组织 Nuxt.js 应用的个性化配置,以便覆盖默认配置。package.json
文件用于描述应用的依赖关系和对外暴露的脚本接口。
别名 | 目录 |
---|---|
~ 或 @ | srcDir |
~~ 或 @@ | rootDir |
默认情况下,srcDir
和 rootDir
相同。
提示: 在您的 vue
模板中, 如果你需要引入 assets
或者 static
目录, 使用 ~/assets/your_image.png
和 ~/static/your_image.png
方式。
路由配置
Nuxt.js 会根据 pages 目录下的目录结构自动生成 vue-router 模块的路由配置
类似Vue-router
中的router-link
、在页面之间跳转使用nuxt-link
标签
例如:
1 | <nuxt-link to="/user">进入个人页</nuxt-link> |
基础路由
假设 pages
的目录结构如下:
1 | pages/ |
那么,Nuxt.js 自动生成的路由配置如下:
1 | router: { |
嵌套路由
当然、你还可以使用另一种目录结构
: user.vue、user目录、user目录下的one.vue
1 | pages/ |
但是你要访问user下的one.vue: /user/one
需要在user.vue
添加<nuxt-child/>
1 | <!-- user.vue --> |
动态路由
在 Nuxt.js 里面定义带参数
的动态路由,需要创建对应的以下划线作为前缀
的 Vue 文件
例如:
1 | pages/ |
这样我们就可以在index.vue
进行操作
1 | <template> |
_id.vue
注意: 通过$route.params
取得的参数名为以下划线作为前缀
的内容 、例: _id.vue、获取就是通过 $route.params.id 传入的参数
1 | <template> |
参数检验
判断参数是否合法来返回页面 validate
简单判断一下以数字开头、validate
返回为假时跳转错误页面
1 | <template> |
我们可以在.nuxt
目录下router.js
看的路由结构
视图
视图的整体布局图如下所示:
模板
定制化默认的 html 模板,只需要在 src 文件夹下(默认是应用根目录)创建一个
app.html
的文件。
默认模板:
1 |
|
例如:
1 |
|
布局
Nuxt.js 允许你扩展默认的布局,或在
layout
目录下创建自定义的布局
默认布局
在vue-router中
、使用router-view
用来显示页面
在nuxt、布局文件(layouts)中添加 <nuxt/>
组件用于显示页面的主体内容。
默认布局default.vue
源码如下
1 | <template> |
自定义布局
如果不想使用nuxt的默认布局页面、可以使用自定义布局:
- 在
layouts
目录下创建布局文件xxx.vue
、并且要有<nuxt />
否则只显示xxx.vue
里的内容 - 在需要的使用的页面中添加
layout: xxx
(不需要.vue)
例如:
假设我们要创建一个 博客布局 并将其保存到layouts/blog.vue
:
1 | <template> |
然后我们必须告诉页面 (即pages/posts.vue
) 使用您的自定义布局:
1 | <template> |
更多有关 layout
属性信息: API 页面 布局
错误页面
你可以通过编辑
layouts/error.vue
文件来定制化错误页面.
这个布局文件不需要包含 <nuxt/>
标签。你可以把这个布局文件当成是显示应用错误(404,500 等)的组件。
官方提供的一个简单的页面 layouts/error.vue
:
1 | <template> |
页面
页面组件实际上是 Vue 组件,只不过 Nuxt.js 为这些组件添加了一些特殊的配置项(对应 Nuxt.js 提供的功能特性)以便你能快速开发通用应用。
Nuxt.js提供的特殊配置项如下表所示:
属性名 | 描述 |
---|---|
asyncData | 最重要的一个键, 支持 异步数据处理,另外该方法的第一个参数为当前页面组件的 上下文对象。 |
fetch | 与 asyncData 方法类似,用于在渲染页面之前获取数据填充应用的状态树(store)。不同的是 fetch 方法不会设置组件的数据。详情请参考 关于 fetch 方法的文档。 |
head | 配置当前页面的 Meta 标签, 详情参考 页面头部配置 API。 |
layout | 指定当前页面使用的布局(layouts 根目录下的布局文件)。详情请参考 关于 布局 的文档。 |
loading | 如果设置为false ,则阻止页面自动调用this.$nuxt.$loading.finish() 和this.$nuxt.$loading.start() ,您可以手动控制它,请看例子,仅适用于在 nuxt.config.js 中设置loading 的情况下。请参考API 配置 loading 文档。 |
transition | 指定页面切换的过渡动效, 详情请参考 页面过渡动效。 |
scrollToTop | 布尔值,默认: false 。 用于判定渲染页面前是否需要将当前页面滚动至顶部。这个配置用于 嵌套路由的应用场景。 |
validate | 校验方法用于校验 动态路由的参数。 |
middleware | 指定页面的中间件,中间件会在页面渲染之前被调用, 请参考 路由中间件。 |
关于页面配置项的详细信息,请参考 页面 API。
HTML头部
Nuxt.js 使用了 vue-meta
更新应用的 头部标签(Head)
and html 属性
。
Nuxt.js 使用以下参数配置 vue-meta
:
1 | { |
重定向
如果我们想访问http://localhost:3000/
想跳转到http://localhost:3000/user
、配置完记得重新启动
方法1:nuxt.config.js
配置
1 | router:{ |
这样访问根目录就会重定向到/user
但是我发现一个问题:如果 根目录/
也就是index.vue
存在的话、通过路由跳转不起作用、解决办法就是删除index.vue
、或者使用中间件的方法
方法2:middleware中间件
在middleware
下创建redirect.js
1 | export default function({isHMR,app,store,route,params,error,redirect}){ |
修改nuxt.config.js
添加middleware
属性、对应的值为middleware
目录下的文件名
1 | router: { |
方法3: 组件中
asyncData
中有redirect
属性
1 | <template> |
异步数据
Nuxt.js 扩展了 Vue.js,增加了一个叫
asyncData
的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。
asyncData 方法
asyncData
方法会在组件(限于页面组件)每次加载之前被调用。简单来说就是在页面直接切换客户端会调用改方法
- 可以在
服务端或路由更新
之前被调用。简单来说就是直接对页面进行刷新时服务端调用并且渲染数据
asyncData
返回的数据融合组件data
方法返回的数据一并返回给当前组件。- 必须将数据用
return
返回出去、否则无法获取数据
注意:由于
asyncData
方法是在组件 初始化 前被调用的,所以在方法内是没有办法通过this
来引用组件的实例对象。所以需要用过 return 返回对象 、如return { dataList : res.data.data.films }
举个例子:
1.axios 方法
在pages/index.vue
通过直接刷新页面、客户端控制台不会打印数据(最新版好像也会打印)、而是在服务端打印
1 | <template> |
只有在其他页面切换回当前页、才会在客户端控制台打印数据
2.aysnc
1 | </script> |
asyncData 参数
通过直接打印asyncData
中的参数可以看到:
里面的参数也就是上下文对象
上下文对象
可通过 API context
来了解该对象的所有属性和方法。
context 变量的可用属性一览:
属性字段 | 类型 | 可用 | 描述 |
---|---|---|---|
app | Vue 根实例 | 客户端 & 服务端 | 包含所有插件的 Vue 根实例。例如:在使用 axios 的时候,你想获取 $axios 可以直接通过 context.app.$axios 来获取 |
isClient | Boolean | 客户端 & 服务端 | 是否来自客户端渲染(废弃。请使用 process.client ) |
isServer | Boolean | 客户端 & 服务端 | 是否来自服务端渲染(废弃。请使用 process.server ) |
isStatic | Boolean | 客户端 & 服务端 | 是否来自 nuxt generate 静态化(预渲染)(废弃。请使用 process.static ) |
isDev | Boolean | 客户端 & 服务端 | 是否是开发 dev 模式,在生产环境的数据缓存中用到 |
isHMR | Boolean | 客户端 & 服务端 | 是否是通过模块热替换 webpack hot module replacement (仅在客户端以 dev 模式) |
route | Vue Router 路由 | 客户端 & 服务端 | Vue Router 路由实例 |
store | Vuex 数据 | 客户端 & 服务端 | Vuex.Store 实例。只有vuex 数据流存在相关配置时可用 |
env | Object | 客户端 & 服务端 | nuxt.config.js 中配置的环境变量,见 环境变量 api |
params | Object | 客户端 & 服务端 | route.params 的别名 |
query | Object | 客户端 & 服务端 | route.query 的别名 |
req | http.Request | 服务端 | Node.js API 的 Request 对象。如果 Nuxt 以中间件形式使用的话,这个对象就根据你所使用的框架而定。*nuxt generate 不可用* |
res | http.Response | 服务端 | Node.js API 的 Response 对象。如果 Nuxt 以中间件形式使用的话,这个对象就根据你所使用的框架而定。*nuxt generate 不可用* |
redirect | Function | 客户端 & 服务端 | 用这个方法重定向用户请求到另一个路由。状态码在服务端被使用,默认 302 redirect([status,] path [, query]) |
error | Function | 客户端 & 服务端 | 用这个方法展示错误页:error(params) 。params 参数应该包含 statusCode 和 message 字段 |
nuxtState | Object | 客户端 | Nuxt 状态,在使用 befonetuxtnetder 之前,用于客户端获取 Nuxt 状态,仅在 universal 模式下可用 |
befonetuxtnetder(fn) | Function | 服务端 | 使用此方法更新 __NUXT__ 在客户端呈现的变量,fn 调用 (可以是异步) { Components, nuxtState } ,参考 示例 |
反向代理
对于前端跨域问题、我们需要配置反向代理
需要安装
1 | npm install --save @nuxtjs/proxy |
在nuxt.config.js
中配置
例如: 猫眼电影 https://m.maoyan.com/ 的首页数据请求API https://m.maoyan.com/ajax/movieOnInfoList?token=
需要如下配置
1 | modules: [ |
page.vue
1 | <template> |
但是如果直接进行刷新是请求 /ajax/movieOnInfoList?token=
服务器没有跨域、会404、所以需要判断一下是服务端还是客户端
通过process.server
、返回true为服务端、接下来简单判断一下就行了
1 | url: process.server ? 'https://m.maoyan.com/ajax/movieOnInfoList?token=' : '/ajax/movieOnInfoList?token=' |
路由动画
路由的动画效果,也叫作页面的更换效果。Nuxt.js提动两种方法为路由提动动画效果,一种是全局的,一种是针对单独页面制作。
全局路由动画
全局动画默认使用page进行设置,例如现在我们为每个页面都设置一个进入和退出时的渐隐渐现的效果
。我们可以先在根目录的assets/css
下建立一个normailze.css
文件。
1 | .page-enter-active,.page-leave-active{ |
编辑nuxt.config.js
1 | css: ['~assets/css/normailze.css'], |
但是只有使用<nuxt-link>
的才有动画效果
单独设置页面动效
给一个页面单独设置特殊的效果时,我们只要在css里改变默认的page,然后在页面组件的配置中加入transition
字段即可。例如,我们想给about页面加入一个字体放大然后缩小的效果
编辑assets/css/normailze.css
test为自定义效果名
1 | .test-enter-active,.test-leave-active{ |
在需要的组件中添加
1 | <script> |