Nuxt.js基础
Nuxt.js介绍
- 一个机基于Vue.js生态的第三方开源服务端应用框架
- 它可以帮我们轻松的使用Vue.js技术栈构建同构应用
- 官网
- Nuxt.js预设了Vue.js开发
服务端渲染
的应用所需要的各种配置,类似于Vue-cli - Nuxt.js集成了Vue2/Vue-Router/Vuex等框架和组件,另外Nuxt.js使用了webpack和vue-loader,babel-loader来处理代码的自动化构建工作(如打包,代码分层,压缩等等)
初始化Nuxt.js
- 初始项目(
推荐
) - 已有的Node.js服务端项目
- 直接把Nuxt当做一个中间件集成到Node Web Server中
- 现有的Vue.js项目
- 非常熟悉Nuxt.js
- 至少百分之10的代码改动
初始化Nuxt.js应用的方式
-
方式一:使用create-nuxt-app脚手架工具(相当于客户端渲染的vue-cli)
-
方式二:手动创建(
新手推荐
) -
创建目录nuxtJs-demo
$ mkdir nuxtJs-demo
$ cd nuxtJs-demo
$ npm init -y
- 下载第三方模块nuxt
npm i nuxt
- 配置package.json中的nuxt命令
- 创建pages目录(pages名称固定,里面全部是视图组件),pages目录下面的index.vue作为服务端渲染的首页
- 启动项目(默认占用3000端口号)
npm run dev
- 我们可以看到在终端执行了编译,因为是同构应用,所以我们可以看到有一个Client和Server,也就是说要构建两个端,Client用于运行客户端,Server用于运行服务端
- 我们发现首页加载出来了,因为Nuxt.js它有自己的一套路由规则,它会自动扫描pages目录,把里面的组件自动提取为路由的配置,index默认指向网站的首页
- 我们早pages目录下面增加一个组件about.vue
案例代码分支说明
- 用不同的分支来管理项目代码,初始化本地仓库
git init
- 在项目根目录下添加.gitignore文件,排除不需要受git管理的文件
git add .
git commit -m "初始化Nuxt.js项目"
- 创建路由的分支
git branch router // 基于当前分支master创建的新分支
git checkout router
路由-基础路由
- Nuxt.js依据pages目录结构自动生成vue-router模块的路由配置
- 要在页面之间使用路由,建议使用<router-link>
- 假设pages的目录结构如下
- 那么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\router.js文件中
- 发现生成的代码其实和客户端渲染的路由配置时一样的,.nuxt\router.js文件中的代码不要手动修改,因为这个文件是Nuxt.js启动项目是自动生成的
路由导航
Nuxt.js中常见的导航有三种方式
- a导航
- 它会刷新整个页面,不要使用
- router-link组件
- 编程式导航,通过js跳转路由,和router中的编程式导航是一样的
a链接导航
- 创建一个新的分支(在master分支基础上)
git checkout -b "路由导航" // 创建了一个新分支,并且切换到该分支上
- 通过a标签跳转到首页,
整个页面会刷新,也就是说会走服务端渲染
nuxt-link导航组件
- 也可以直接写router-link,详细用法和vue-router一样
- 不刷新跳转
编程式导航
- 详细用法和vue-router一样
动态路由
-
Vue Router动态路由匹配
-
Nuxt.js动态路由
- 在Nuxt.js里面定义带参数的动态路由,需要创建对应的
以下划线为前缀
的vue文件或目录 - 以下目录结构
- 在Nuxt.js里面定义带参数的动态路由,需要创建对应的
-
Nuxt.js生成对应的路由配置如下
-
当我们输入
- 动态路由参数的获取,和Vue-router中一样,在$route.params对象中
嵌套路由
- Vue Router嵌套路由
- Nuxt.js嵌套路由
-
创建嵌套子路由,需要添加一个Vue文件,同时添加一个与
该文件同名
的目录来存放子视图组件 -
注意:在父组件(.vue文件)内增加<nuxt-child/>用于显示子视图的内容,相当于<router-view/>
-
父组件
- 子组件
- 子组件
-
路由配置
- 链接
- 想要对路由进行额外的配置,可以给router配置相关属性,下面介绍几个常见的属性配置
- base 设置网站的根路径 ,默认是"/",在项目根目录下新建nuxt.config.js,该文件是nuxt.js的配置文件
- extendRoutes 如果要扩展Nuxt.js创建的路由,可以通过extendRoutes选项执行此操作,例如创建自定义路由
假如我们已经存在一个about页面,可以通过http://localhost:3000/about来访问,假如我们还想有一个路径也指向about页面,可以自定义扩展路由
视图
- 视图由
模板
(html页面),布局
(布局组件,相当于所有组件的父路由)和页面组件
组成
模板
- 可以定制化Nuxt.js默认的应用模板
- 定制默认的html模板,只需要在根目录下创建一个app.html的文件
- Nuxt.js使用的默认模板是:
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
</head>
<body {{ BODY_ATTRS }}>
{{ APP }}
</body>
</html>
)
- 最关键的是{{app}},最终的渲染内容会注入到这里,其他的{{ HTML_ATTRS }}等内容可以在配置文件中修改
布局
- 可以在模板和具体的页面之间再加一层布局组件
- Nuxt.js允许扩展默认的布局,或在layouts目录下创建自定义的布局
默认布局组件
- 可以通过layouts/default.vue文件来扩展应用的默认布局,类似于嵌套组件,可以认为是所有组件的父组件
提示:别忘了在布局文件中添加\<nuxt/>组件用于显示页面的主体内容
- 默认布局的源码如下
<template>
<Nuxt /> // 直接显示页面组件的内容
</template>
- layouts可以给所有的页面设置公共的布局(导航栏和侧边栏等)
- layouts/default.vue是默认的布局组件,我们可以在页面中的layout选项(默认值是default)指定布局组件,不管在页面组件中写不写layout: ‘default’,页面组件都会引用默认的布局,如果想引用其他的布局,可以在layouts目录下定义布局
自定义布局组件
异步数据-asyncData
服务端渲染页面期间获取动态数据
Nuxt.js异步数据-asyncData方法
- Nuxt.js扩展了Vue.js,增加了一个叫asyncData的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据
- 模拟接口数据,static目录下的资源是可以直接被访问的
- 在地址栏输入http://localhost:3000/data.json => nuxt服务中默认把static暴露出来,允许公开访问,不经过webpack编译打包,可以用它来充当数据接口
- 在服务端,首页异步获取数据
npm i axios
- 错误url
- 正确url
- 控制台请求到了数据
- 返回的数据对象可以直接在页面中使用,
asyncData函数中返回的数据会和页面data中的数据混合在一起,给页面来使用
- 我们怎么判断asyncData函数是在服务端渲染页面期间触发的呢?
- Nuxt.js为了调试方便,它把服务端渲染的日志也输出到客户端,但为了做一个区分,它用Nuxt SSR将日志包裹起来了
asyncData函数除了在服务端渲染页面期间运行,也会在客户端路由导航之前运行
- 路由导航时,由about页面进入首页
asyncData方法小结
- 基本用法
- 它会将asyncData返回的数据融合组件data方法返回数据一并给组件
- 调用时机:服务端渲染期间和客户端路由更新数据之前
- 注意事项
- 只能在页面组件中使用
- 没有this,因为它是在组件初始化之前被调用的(也就是渲染之前调用的,无论是服务端还是客户端渲染)
只能在页面组件中使用
- pages目录下的组件就是页面组件,假如我们创建一个非页面组件,在components目录下放的公共组件就是非页面组件
- 在iindex.vue中引入foo子组件f(
foo组件不是页面组件
)
如果想在子组件foo中拿到服务端渲染的动态数据,可以在页面组件中通过asyncData获取到的动态数据传给子组件
- 当你想要动态页面的内容有利于SEO或者是提升首屏渲染速度的时候,就在asyncData中发送请求拿数据
- 如果是非异步数据或者普通数据,则正常的初始化到data中即可
没有this,因为它是在组件初始化之前被调用的
异步数据-上下文对象
-
在index.vue中
-
在_id.vue中
-
点击湖北省
-
我们在_id.vue页面组件中想要根据地址栏传入的id=1,来调取接口动态匹配id=1的内容,但是在asyncData函数中怎么获取地址栏参数呢,因为我们上面提到过,不能在asyncData函数中使用this.所以this.$route.params是不可取的
-
asyncData函数有一个参数,叫做context(形参,可以为任意名称),也就是上下文对象,我们打印这个对象
-
对_id.vue组件改造
<template>
<div>
<h1>{{ article }}</h1>
</div>
</template>
<script>
import axios from "axios"
export default {
name: "articlePage",
async asyncData (context) {
const { data } = await axios({
method: "GET",
url: "http://localhost:3000/data.json"
})
const id = Number.parseInt(context.params.id)
return {
article: data.post.find(item => {
return item.id === id
})
}
}
}
</script>