当前位置:网站首页>Nuxt.js数据预取
Nuxt.js数据预取
2022-07-01 15:43:00 【黑猫几绛】
本文采用的技术框架有:
后台:Express + MongoDb
前台:Vue2.js + [email protected]
在Nuxt中发送请求有两种方案:
前后台分离的方案 (数据到页面的过程是在浏览器完成的) 网页源代码中没有数据
前台发送请求 -> 服务器处理请求 -> 前台接收到数据 -> 前台把数据渲染到页面
凡是通过js的行为获取到的数据都是前后台分离的
服务端渲染的方案
- asyncData:写在页面组件中,获取页面中需要服务端渲染的数据,把数据return给页面 (直接在页面上使用数据)
- nuxtServerInit:在store/index.js里面写,永远在服务器运行,只会在页面首次加载的时候执行一次 (适合写一些全局共享的数据)
- fetch:写在页面组件中,获取页面中需要服务端渲染的数据,把数据存到vuex (父子组件的数据共享可以优先使用fetch)
一、asyncData
在组件加载之前先去发起请求拿到数据,提前将数据渲染在页面,然后返回的页面中将包含数据。
- 由于在客户端创建实例化之前加载,所以不能使用 this,钩子提供一个参数,可以获取上下文对象(
{isDev, route, store, env, params, query, req, res, redirect, error}
等),从而做一些简单操作。 - 只能在路由页面组件中使用(每次加载页面都会调用),在自定义组件中无效。
- 返回的数据最终将与 data 数据合并,为了保证不发生页面渲染错误,返回的键应事先在 data 里声明好(如果 template 中没有使用所需属性,则并不必声明)。
1.1 一个例子
我们初次打开某个网站时,页面中会显示立即登录/注册的字样
在成功登录后,该部分会被替换为
现在的需求是,通过服务端渲染的方式将用户信息显示在页面上
1.2 初步分析
在用户成功登录的时候,可以将个人信息保存至服务器的session中,也就意味着,我们似乎可以通过session获取到用户信息。
router.post("/singin", async (req, res) => {
const {
username, password } = req.body;
const findUser = await User.findOne({
username, password });
//登录成功
if (findUser) {
// 个人信息保存至服务器的session中
req .session.user = findUser;
res.json({
code: 0,
msg: "登录成功"
})
}
//登录失败
else {
res.json({
code: -1,
msg: "账号或者密码出错"
})
}
})
可是,session保存在服务器中,而我们需要的是在浏览器中显示数据。显然,浏览器中拿不到服务器中的数据。
上面加粗的文字似乎存在问题,看起来写一个接口,在进入首页时通过接口请求session中的数据好像也可以,尝试一下。
1.2.1 编码
请求session数据的接口:
router.get("/userInfo", (req, res) => {
if (req.session.user) {
res.json({
code: 0,
user: req.session.user,
msg: "获取用户信息成功"
})
}
else {
res.json({
code: 0,
user: null,
msg: "当前用户未登录"
})
}
})
前台页面:
import {
request } from "@/utils/request";
export default {
async asyncData() {
// 封装后的axios请求方法
let result = await request.get("/users/userInfo");
console.log(result);
return {
result
}
},
};
1.2.2 测试
在首页登录后刷新页面:
此时浏览器中可以成功显示登录后的数据,说明用户已经登录:
而服务器中则显示用户未登录:
此时就需要分析一下asyncData
这个函数的用法了。
asyncData既可能运行在浏览器,又可能运行在服务器。
刷新页面的时候,asyncData方法运行在在服务器,所以数据消息会在服务器中打印,通过打印我们发现获取不到session数据。
路由跳转<nuxt-link>
的时候,asyncData方法运行在浏览器,所以数据消息会在浏览器中打印,通过打印我们发现可以获取session数据。
为什么打印的位置不一样,session数据的打印也不一样呢?
这里涉及到了session
的原理:
- 用户在通过接口登录后,用户信息将会被保存到服务器的session中
- session内部会创建cookie作为一个凭证,然后接口将这个凭证返回给浏览器保存
- 浏览器下次发送请求的时候会带上这个cookie凭证
所以,上面的问题的原因就在于:
请求从浏览器发出去的时候,浏览器会自动携带session对应的cookie发送服务器,所以服务器就可以根据cookie获取到数据
而请求从服务器发出去的时候,就没有session对应的cookie,所以获取不到登录的用户信息
在这里我绘制一张图来描述,可能会更加清晰:
在上面的错误操作中,我们采用的方法是调用asyncData
方法,这个方法在服务端中向接口发起请求,而不是浏览器发起的请求。由于cookie存在于浏览器中保存,所以用户登陆后。服务器中显示的是用户未登录。
在第二章中介绍具体的解决方法。
二、nuxtServerInit
这个方法只能在vuex中使用,永远只会在服务器运行,永远只是首屏加载的时候执行一次
可以接收两个参数:
- 第一个参数保存着vuex信息
- 第二个参数是上下文对象(context)
也就是说,在首屏加载过后,无论是通过this.$router.push
还是<nuxt-link>
跳转,该方法都不会执行,除非是再次刷新页面触发加载。
这意味着,采用nuxtServerInit
获取到的数据,在首屏加载过后无法通过上述两个方法将数据渲染到页面上。
// 负责登录的函数
submitForm() {
// 这里采用了Elemnet-ui的表单验证方法
this.$refs.loginForm.validate(async (valid) => {
//表单校验通过,可以发送请求
if (valid) {
let result = await axios.post("/users/singin", {
username: this.ruleForm.name,
password: CryptoJS.MD5(this.ruleForm.pwd).toString(),
});
// 通过window.location.href = "/"刷新浏览器,此时可以将数据渲染到页面上
result.code === 0
// ? this.$router.push('/') 无效
? (window.location.href = "/")
: (this.err = result.msg);
}
});
},
编写vuex:
import { request } from '@/utils/request'
export const state = () => ({
user: null,
})
export const mutations = {
SET_USER(state, payload) {
state.user = payload
}
}
export const actions = {
// 产品分为前端和后端
// 采用了SSR的前端可以分为 前端客户端[具体的html页面] + 前端服务端
// 这里的 nuxtServerInit 运行在 前端服务端中
// 该方法的第二个参数,可以获取到服务端的上下文对象
// 查阅文档可知,在这里可以获取到nodejs服务器发起请求时的 req 数据
async nuxtServerInit({ commit }, { req }) {
const user = req.session.user;
commit("SET_USER", user)
}
}
现在回到首页,将vuex中的数据读取出来:
<template>
<div>
<template v-if="user">
欢迎您,
<span class="username">{
{ user.username }}</span>
[<nuxt-link to="/exit">退出</nuxt-link>]
</template>
<template v-else>
<nuxt-link to="/login">立即登录</nuxt-link> |
<nuxt-link to="/register">注册</nuxt-link>
</template>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed:{
...mapState(['user'])
}
};
</script>
此时可以成功将数据渲染在页面上。
三、fetch
这里仅讨论v2.12以下的版本
该方法与asyncData差不多,不过它无法将数据通过return
的方式返回页面渲染。
如果页面组件设置了 fetch
方法,它会在组件每次加载前被调用(在服务端或切换至目标路由之前)。
fetch
方法的第一个参数是页面组件的上下文对象context
,我们可以用 fetch
方法来获取数据填充应用的状态树。为了让获取过程可以异步,你需要返回一个 Promise,Nuxt.js 会等这个 promise 完成后再渲染组件。
注意: 无法在内部使用this
获取组件实例,fetch
是在组件初始化之前被调用
比如:
<template>
<Son></Son>
</template>
<script>
export default {
fetch({ store, params }) {
return axios.get('/userList').then( res => {
store.commit('ADD_USER', res.data)
})
}
}
</script>
边栏推荐
- Hardware development notes (9): basic process of hardware development, making a USB to RS232 module (8): create asm1117-3.3v package library and associate principle graphic devices
- ABAP-屏幕切换时,刷新上一个屏幕
- 张驰课堂:六西格玛数据的几种类型与区别
- Day 3 of rhcsa study
- 【目标跟踪】|STARK
- Go语学习笔记 - gorm使用 - 表增删改查 | Web框架Gin(八)
- 【开源数据】基于虚拟现实场景的跨模态(磁共振、脑磁图、眼动)人类空间记忆研究开源数据集
- Is JPMorgan futures safe to open an account? What is the account opening method of JPMorgan futures company?
- 【显存优化】深度学习显存优化方法
- Qt+pcl Chapter 6 point cloud registration ICP Series 2
猜你喜欢
MySQL advanced 4
工厂高精度定位管理系统,数字化安全生产管理
AVL 平衡二叉搜索树
【300+精选大厂面试题持续分享】大数据运维尖刀面试题专栏(三)
Tanabata confession introduction: teach you to use your own profession to say love words, the success rate is 100%, I can only help you here ~ (programmer Series)
Tensorflow team: we haven't been abandoned
张驰咨询:家电企业用六西格玛项目减少客户非合理退货案例
《性能之巅第2版》阅读笔记(五)--file-system监测
2022 Moonriver全球黑客松优胜项目名单
Guide de conception matérielle du microcontrôleur s32k1xx
随机推荐
Some abilities can't be learned from work. Look at this article, more than 90% of peers
One revolution, two forces, three links: the "carbon reduction" roadmap behind the industrial energy efficiency improvement action plan
Pocket Network为Moonbeam和Moonriver RPC层提供支持
2022-07-01日报:谷歌新研究:Minerva,用语言模型解决定量推理问题
【STM32-USB-MSC问题求助】STM32F411CEU6 (WeAct)+w25q64+USB-MSC Flash用SPI2 读出容量只有520KB
Is JPMorgan futures safe to open an account? What is the account opening method of JPMorgan futures company?
七夕表白攻略:教你用自己的专业说情话,成功率100%,我只能帮你们到这里了啊~(程序员系列)
Rhcsa fourth day operation
[pyGame practice] do you think it's magical? Pac Man + cutting fruit combine to create a new game you haven't played! (source code attached)
Connect the ABAP on premises system to the central inspection system for custom code migration
Detailed explanation of stm32adc analog / digital conversion
Deep operator overloading (2)
An intrusion detection model
【OpenCV 例程200篇】216. 绘制多段线和多边形
微信小程序02-轮播图实现与图片点击跳转
6.2 normalization 6.2.6 BC normal form (BCNF) 6.2.9 normalization summary
大龄测试/开发程序员该何去何从?是否会被时代抛弃?
Redis high availability principle
Samsung took the lead in putting 3nm chips into production, and Shanghai's fresh master students can settle directly. Nankai has established a chip science center. Today, more big news is here
使用swiper制作手机端轮播图