当前位置:网站首页>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>
边栏推荐
- 微信小程序01-底部导航栏设置
- Task.Run(), Task.Factory.StartNew() 和 New Task() 的行为不一致分析
- Wechat applet 01 bottom navigation bar settings
- 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)
- [300 + selected interview questions from big companies continued to share] big data operation and maintenance sharp knife interview question column (III)
- 2022 Moonriver全球黑客松优胜项目名单
- What time do you get off work?!!!
- 【显存优化】深度学习显存优化方法
- The last picture is seamlessly connected with the first picture in the swiper rotation picture
- Is JPMorgan futures safe to open an account? What is the account opening method of JPMorgan futures company?
猜你喜欢
Reading notes of top performance version 2 (V) -- file system monitoring
RT-Thread Env 工具介绍(学习笔记)
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
硬件开发笔记(九): 硬件开发基本流程,制作一个USB转RS232的模块(八):创建asm1117-3.3V封装库并关联原理图元器件
MySQL高级篇4
Returning to the top of the list, the ID is still weak
Automatique, intelligent, visuel! Forte conviction des huit conceptions derrière la solution sslo
u本位合约和币本位合约有区别,u本位合约会爆仓吗
Hardware design guide for s32k1xx microcontroller
HR面试:最常见的面试问题和技巧性答复
随机推荐
Task.Run(), Task.Factory.StartNew() 和 New Task() 的行为不一致分析
Sort out the four commonly used sorting functions in SQL
Stm32f411 SPI2 output error, pb15 has no pulse debugging record [finally, pb15 and pb14 were found to be short circuited]
Wechat applet 03 - text is displayed from left to right, and the block elements in the line are centered
Redis seckill demo
The newly born robot dog can walk by himself after rolling for an hour. The latest achievement of Wu Enda's eldest disciple
Pico,能否拯救消费级VR?
[300 + selected interview questions from big companies continued to share] big data operation and maintenance sharp knife interview question column (III)
Tensorflow team: we haven't been abandoned
Qt+pcl Chapter 6 point cloud registration ICP Series 2
自动、智能、可视!深信服SSLO方案背后的八大设计
求求你们,别再刷 Star 了!这跟“爱国”没关系!
Overview | slam of laser and vision fusion
An intrusion detection model
Pnas: brain and behavior changes of social anxiety patients with empathic embarrassment
[video memory optimization] deep learning video memory optimization method
Automatic, intelligent and visual! Deeply convinced of the eight designs behind sslo scheme
Returning to the top of the list, the ID is still weak
如何写出好代码 - 防御式编程指南
HR面试:最常见的面试问题和技巧性答复