Nuxt.js——学习笔记
声明
:
- 本博客所用到的图片资料等如果来自互联网(知道来源的)将标注,没标注的就是暂时不清楚具体出处的,还望告知。
- 本博客所提供的的资料仅供本人或者各位博友学习参考,不会给我带来收益。
- 如有知识点错误还望指正,感谢。
一、Nuxt.js
1.1 Nuxt.js 简介
移动互联网的兴起促进了web前后端分离开发模式的发展,服务端只专注业务,前端只专注用户体验,比如流行的vue.js实现了功能强大的前端渲染。 但是,对于有SEO需求的网页如果使用前端渲染技术去开发就不利于SEO了,有没有一种既使用vue.js 的前端技术也实现服务端渲染的技术呢?
Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可以用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。
【重点】利用Nuxt.js的服务端渲染的特点来解决Vue项目的SEO(搜索引擎优化)问题。
1.2 Nuxt.js 服务端渲染
下图展示了从客户端请求到 Nuxt.js 进行服务端渲染的整体的工作流程:
1)用户打开浏览器,输入网址请求到 Node.js 中的前端 View 组件;
2)部署在 Node.js 的应用 Nuxt.js 接收浏览器请求,并请求服务端获取数据 ;
3)Nuxt.js 获取到数据后进行服务端渲染 ;
4)Nuxt.js 将 html 网页响应给浏览器;
二、CSR 和 SSR
2.1 CSR
CSR
(Client side render,客户端渲染
)。客户端(浏览器) 使用AJAX向服务端发起 http 请求,获取到了想要的数据,开始渲染 html 网页,生成 dom 元素,并最终将网页内容展示给用户。
客户端渲染的特点:
- 在服务端只是给客户端响应数据,而不是html网页;
- 客户端(浏览器)负责获取服务端的数据生成dom元素;
2.2 SSR
SSR
(Server Side Render,服务端渲染
)是在服务端完成页面的内容渲染,而不是在客户端完成页面内容的渲染。
简单的 ssr 服务渲染流程;
【图片来源:互联网(暂不知来源)】
SSR并不是前端特有的技术,我们学习过的 JSP 技术和 Thymeleaf 技术就是典型的SSR:
服务端渲染的特点:
- 在服务端生成 html 网页的 dom 元素;
- 客户端(浏览器)只负责显示 dom 元素内容;
2.3 两种方式的优缺点
客户端渲染:
- 缺点:不利于网站进行SEO,因为网站大量使用javascript技术,不利于搜索引擎抓取网页。
- 优点:客户端负责渲染,用户体验性好,服务端只提供数据不用关心用户界面的内容,有利于提高服务端的开发效率。
- 适用场景:对SEO没有要求的系统,比如后台管理类的系统,如电商后台管理,用户管理等。
服务端渲染:
- 优点:有利于SEO,网站通过 href 的 url 将搜索引擎直接引到服务端,服务端提供优质的网页内容给搜索引擎。
- 缺点:服务端完成一部分客户端的工作,通常完成一个需求需要修改客户端和服务端的代码,开发效率低,不利于系统的稳定性。
- 适用场景:对SEO有要求的系统,比如:门户首页、商品详情页面等。
三、开始使用
参考官网
3.1 手动安装
1) 在vscode中新建一个空文件夹,并使用终端进入该目录层级。
mkdir my-nuxt-app
cd my-nuxt-app
2) 在项目根目录下创建package.json
文件(文件内容如下):
{
"name": "my-nuxt-app",
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"generate": "nuxt generate",
"start": "nuxt start"
}
}
备注:
- scripts 定义将使用命令npm run < command >或yarn < command >。
- 什么是
package.json
文件?该文件就像您项目的身份证。它包含所有项目依赖项等等。
3) 安装 Nuxt;一旦 package.json 被创建,通过 npm 或 yarn 命令就可以将 nuxt 安装到项目;
#在项目根目录下安装nuxt
npm install nuxt
注意:
- 此命令将nuxt作为依赖项添加到您的项目中,并将其添加到您的 package.json. 该
node_modules
目录也将被创建,这是您所有已安装的包和依赖项的存储位置。- 还会创建一个 yarn.lock 或
package-lock.json
,以确保项目中安装的包的一致安装和兼容依赖项。
3.2 快速入门
Nuxt 会为项目将每个在pages
目录下的*.vue
文件转换为一个路由。(不需要我们手动添加路由设置)
1) 在项目中创建一个 pages 目录。
mkdir pages
2) 在 pages 目录中创建一个 index.vue 文件;(文件内容如下)
<template>
<h1>Hello Nuxt!</h1>
</template>
3) 启动项目;
npm run dev
项目运行在 http://localhost:3000
3.3 路由(导航)
重点:如果要在应用程序中进行路由,我们所要做的就是在 pages 文件夹中创建 .vue 文件。
解释:Nuxt 会自动为 pages 目录下的 vue 文件生成 vue-router(vue路由),即我们不需要写路由配置,Nuxt 还为您提供所有路线的自动代码拆分。
3.3.1 基本路由1
/user
指向 pages/user.vue
页面;
举例如下
pages/index.vue
<template>
<div>
<h1>首页</h1>
<!-- 对于指向您网站内页面的所有链接,请使用<NuxtLink> -->
<NuxtLink to="/banner">banner图</NuxtLink><br/>
<NuxtLink to="/about">关于我们</NuxtLink><br/>
<!-- 指向其他网站的链接,则应使用该<a>标签 -->
<a href="https://www.baidu.com">百度一下</a>
</div>
</template>
pages/banner.vue
<template>
<div>
<h1>banner部分</h1> <br/>
<NuxtLink to="/">返回首页</NuxtLink>
</div>
</template>
3.3.2 基本路由2
/lend
指向 pages/lend/index.vue
页面;
<template>
<div>
<h1>pages/lend/index.vue</h1> <br/>
<NuxtLink to="/">返回首页</NuxtLink>
</div>
</template>
3.3.3 动态路由
/lend/1
、lend/2 等 指向 pages/lend/_id.vue
页面,并通过 this.$route.params.id
获取动态路径;(该组件的文件名就叫 _id.vue)
<template>
<h1>投资产品 {{ id }}</h1>
</template>
<script>
export default {
data() {
return {
id: null,
}
},
created() {
this.id = this.$route.params.id
},
}
</script>
3.3.4 嵌套路由
如果 pages/lend.vue
和 pages/lend/index.vue
同时存在,我们可以利用嵌套路由<nuxt-child />
,来实现不同路由的跳转;
<template>
<div style="border:1px red solid">
<div style="background-color:#16a085;">
<h1>pages/lend.vue中的内容</h1> <br />
<nuxt-link to="/lend">pages/lend/incex.vue</nuxt-link><br/>
<nuxt-link to="/lend/2">pages/lend/_id.vue</nuxt-link>
</div>
<div style="background-color:#3498db;">
<!-- 代表嵌套路由的出口,即上面的两个是子路由(必须要有) -->
<nuxt-child />
</div>
</div>
</template>
查看 根路径下的 /my-nuxt-app/.nuxt/router.js
路由文件,可以看到嵌套路由的配置,如下:
{
path: "/lend",
component: _6e98c322,
children: [{
path: "",
component: _6c5fb1c0,
name: "lend"
}, {
path: ":id",
component: _f9051cf0,
name: "lend-id"
}]
},
运行效果图:
解释:
- 在访问父路由的时候,如果父路由中有
<nuxt-child />
嵌套路由入口,则会在该位置显示第一个子路由关联到的组件(/父目录/index.vue)的内容信息。- 有点像 tab 栏。
3.4 Nuxt远程数据的获取与绑定(重点)
3.4.1 整合 axios
我们可以引入Nuxt中封装的axios组件,功能更多,编程更简单
参考:nuxt / axios
在 nuxt.config.js
的 module.exports
里面引入 axios 的配置;
module.exports = {
server: {
port: 3000, // default: 3000
},
//引入 axios 的配置
modules: [
'@nuxtjs/axios', //引入axios模块
],
// ssr: false, //设置为false表示客户端渲染,true为服务器端渲染,默认为true
}
3.4.2 客户端渲染
在 pages/index.vue 中添加如下代码 ;
<template>
{{ ip }}
</template>
<script>
export default {
data() {
return {
ip: null,
}
},
created() {
this.$axios.$get('http://localhost:10010').then((response) => {
console.log(response)
this.ip = response
})
},
}
</script>
get()
和$get()
的区别:
get()
方法回调函数中response是响应实体,里面有data属性;$get()
方法回调函数中response是响应实体.data
。 $get()是抓取data的快捷方式;
3.4.3 服务器端渲染
asyncData({ $axios }) {
console.log('asyncData')
$axios.$get('http://localhost:10010').then((response) => {
console.log(response)
})
return {
ip: response, //这种写法的问题是:前面的远程调用是异步的,无法在这获取到response
}
},
可以将异步调用改为同步调用,使用async
和await
关键字使远程调用变为同步,同时让程序更简洁;
async asyncData({ $axios }) {
console.log('asyncData')
let response = await $axios.$get('http://localhost:10010')
return {
ip: response,
}
},
3.4.4 axios 全局选项
在nuxt.config.js
中添加如下配置;
axios: {
// Axios options here
baseURL: 'http://localhost:10010',
},
asyncData中直接写相对路径;
let response = await $axios.$get('/')
3.4.5 axios 拦截器
创建拦截器插件,文件位置 plugins/axios.js
;
export default function({ $axios, redirect }) {
$axios.onRequest((config) => {
console.log('执行请求拦截器 ' + config.url)
})
$axios.onResponse((response) => {
console.log('执行响应拦截器 ')
return response
})
$axios.onError((error) => {
console.log(error) // for debug
})
}
nuxt.config.js
中配置拦截器插件;
plugins: [
'~/plugins/axios', //axios 拦截器插件
'~/plugins/element-ui.js',
]
强烈推荐参考官网 nuxt/axios 官网
3.5 axios 使用(get/post 传参)
get 和 post 方式传参!
3.5.1 $ axios.$get
1) 不带参数
methods: {
//查询账户余额
fetchAccount() {
//从cookie中获取 userInfo 对象(需要在 script 块中加入代码: import cookie from 'js-cookie')
let userInfo = cookie.get('userInfo')
//如果userInfo为空就调用后端接口查询账户金额
if (userInfo) {
this.$axios.$get('/api/core/userAccount/auth/getAccount').then((resp) => {
this.account = resp.data.account
})
},
},
2) Restful 风格传参
//计算收益的函数
getInterestCount() {
this.$axios.$get(`/api/core/lend/getInterestCount/${this.invest.investAmount}/${this.lend.lendYearRate}/${this.lend.period}/${this.lend.returnMethod}`).then((response) => {
this.interestCount = response.data.interestCount
})
},