NextJs 渲染篇 - 什么是CSR、SSR、SSG、ISR 和服务端/客户端组件
NextJs 渲染篇 - 什么是CSR、SSR、SSG、ISR 和服务端/客户端组件
- 前言
- 一. 什么是CSR、SSR、SSG、ISR
- 1.1 CSR 客户端渲染
- 1.2 SSR 服务端渲染
- 1.3 SSG 静态站点生成
- ① 没有数据请求的页面
- ② 页面内容需要请求数据
- ③ 页面路径需要获取数据
- 1.4 ISR 增量静态再生
- 1.5 四种渲染方式的对比和总结
- 二. 服务端组件和客户端组件
- 2.1 水合(Hydration)
- 2.2 Suspense 和 Streaming
- 2.3 React Server Components 和 SSR
- 2.4 服务端组件 VS 客户端组件
前言
在 NextJs 初级篇 中讲了关于NextJs
的安装、路由、中间件等内容,本篇文章来一起学习一下关于 NextJs 的渲染知识。
一. 什么是CSR、SSR、SSG、ISR
我们先来说下这几个名词的专业解释:
CSR(Client-side Rendering)
:客户端渲染。SSR(Server-side Rendering)
:服务端渲染。SSG(Static Site Generation)
:静态站点生成。ISR(Incremental Static Regeneration)
:增量静态再生。
接下来我们对每种渲染进行详细的解释以及NextJs
的实现案例。后续都用简称来说明。
1.1 CSR 客户端渲染
CSR
常规的实现就是我们常规的React
开发,就是一种客户端渲染:
- 一般浏览器会下载一个非常小的
HTML
文件以及必要的JS
文件。 - 我们在
JS
中发送请求,更新DOM
和渲染页面。比如useEffect
钩子函数中初始化页面数据。
NextJs
中,在AppRouter
模式下,使用CSR
,在组件中使用 'use client'
标明,用useEffect
请求初始化数据渲染即可,例如以下伪代码:
'use client'
import React, { useEffect, useState } from 'react'
const Home = () => {const [data, setData] = useState<any>(null);useEffect(() => {setTimeout(() => {setData({ id: 1 })}, 5000);})return <>{data ? <span id='test'>{data.id}</span> : 'Loading'}</>
}export default Home
刚开始的时候页面长这个样子:
渲染完毕后:
1.2 SSR 服务端渲染
SSR 服务渲染有啥好处,我们举个例子:假如客户端网速非常差,那么在CSR
的情况下,由客户端发起请求加载数据就会非常慢,倘若我们把加载数据的工作丢给服务端,而服务器的网络情况非常良好,那么最终的首屏加载时长FCP
也就更短。
但是同样的,由于SSR
情况下,它的响应时长还算上了数据的请求,因此响应时间更长,最终的TTFB
指标也就更长。
例如NextJs
中要想实现SSR
,我们可以在pages
目录下创建个ssr.tsx
文件:
内容如下,我们需要借助getServerSideProps
函数来获取数据并通过props
返回给前端组件,
// pages/ssr.js
export async function getServerSideProps() {const data = [{ 'id': 1, 'name': 'ljj' }]return { props: {data} }
}
// getServerSideProps 传入的是什么,这里就接收什么名称的参数
const SSR = ({ data }: any) =>{return <span id='test'>{JSON.stringify(data)}</span>
}
export default SSR;
1.3 SSG 静态站点生成
SSR
,会在构建阶段,就将页面编译成一个静态的HTML
文件。
例如,当我们的站点,上面的Layout
总是一样的时候,或者是面对所有的用户,展示的都是一个内容,那么这块部分就没必要在用户请求页面的时候来渲染。干脆提前编译为HTML
文件,在用户访问的时候,直接返回一个HTML
则会更快。
NextJs
中实现SSG
,分为这么几种情况:
① 没有数据请求的页面
例如:
const SonA = () => {return <>我是SonA!!!</>
}
export default SonA
这种页面,NextJs
在构建的时候就会生成一个单独的HTML
文件,
② 页面内容需要请求数据
如果我们的HTML
文件的某些内容,需要通过接口获取,那怎么办?这种方式就需要结合 getStaticProps
函数来使用。例如我们在pages目录下创建ssg.tsx
文件:
export default function SSG({ data }: any) {return (<ul>{data.map((item: any) => (<li key={item.id}>{item.title}</li>))}</ul>)
}
export async function getStaticProps() {const res = await fetch('https://jsonplaceholder.typicode.com/posts')const data = await res.json()return {props: {data,},}
}
getStaticProps
这个函数,会在构建的时候被调用,然后通过props
属性传递给组件。
③ 页面路径需要获取数据
我们知道NextJs
中有一个动态路由,只需要将动态部分用[]
括起来即可,例如:
那如果我们希望这类路由的页面都通过SSG
来实现:
- blog/1
- blog/2
- …
如何实现?我们在 getStaticProps
的基础上,追加一个函数的实现 getStaticPaths
:
export default function Blog({ post }: any) {return (<><header>{post.title}</header><main>{post.body}</main></>)
}
export async function getStaticPaths() {const res = await fetch('https://jsonplaceholder.typicode.com/posts')const posts = await res.json()const paths = posts.map((post: any) => ({params: { id: String(post.id) },}))return { paths, fallback: false }
}export async function getStaticProps({ params }: any) {// 如果路由地址为 /posts/1, params.id 为 1const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`)const post = await res.json()return { props: { post } }
}
getStaticProps
用来定义获取的数据传递给HTML
getStaticPaths
则用来定义哪些路径将会实现SSG
。fallback
返回false
代表当访问这些静态路径以外的,则返回404.
当我们执行npm run build
的时候,可以看到构建产物如下,这些都是SSG
的产物。
1.4 ISR 增量静态再生
我们的一些页面例如博客,主题内容可能永远是不变的,但是部分内容是改变的,例如这篇博客的阅读量。在我们使用SSG
的情况下,这个HTML
文件就被固定生成了,那么如何让这个阅读量能够实时的改变呢?那么在SSG
的基础上,就有了ISR
。
- 在访问某个
SSG
页面的时候,可能依旧是老的HTML
内容。 - 但是与此同时,
NextJs
会静态编译一个新的HTML
文件。 - 那么在第二次访问的时候,就会变成新的
HTML
文件内容了。
我们在``案例的基础上,稍微改造一下:
export default function Blog({ post }: any) {return (<><header>{post.title}</header><main>{post.body}</main></>)
}
export async function getStaticPaths() {const res = await fetch('https://jsonplaceholder.typicode.com/posts')const posts = await res.json()const paths = posts.map((post: any) => ({params: { id: String(post.id) },}))return { paths, fallback: 'blocking' }
}
function getRandomInt(max: number) {return Math.floor(Math.random() * max);
}
export async function getStaticProps({ params }: any) {const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${getRandomInt(100)}`)const post = await res.json()return {props: { post },revalidate: 3,}
}
可以看到,我们在 getStaticProps
函数中,多暴露了一个属性:revalidate
。代表发生请求的时候,需要间隔多少秒才会更新页面,我这里填的是3,也就是3秒会刷新一次,构建新的HTML
。
注意:ISR
需要在生产环境下生效。因此我们npm run build
之后再npm run start
,
结果如下:
可以看到我们第一次访问以及接下来的3秒内,博客的内容都是一样的。但是3秒过后,博客的内容就发生了改变,实际上是HTML
刷新了。每3秒就会重新构建一个新的HTML
,缓存3秒的时长。
1.5 四种渲染方式的对比和总结
CSR | SSR | SSG | ISR | |
---|---|---|---|---|
名词解释 | 客户端渲染 | 服务端渲染 | 静态站点生成(即生成HTML 文件返回给客户端) | 增量静态再生 |
实现方式 | 例如React 的useEffect | 借助getServerSideProps 函数,在服务端请求数据并通过props 属性传递给组件 | ①没有数据请求的页面自动生成HTML ②文件内容则借助 getStaticProps 函数获取数据,再生成静态文件 ③ 动态路由则借助getStaticPaths 来指定生成HTML 的路径 | 在SSG的基础上getStaticProps函数追加暴露revalidate 属性,代表刷新HTML 的时长 |
优缺点 | 只有少量的静态文件先加载,由客户端发起请求触发渲染, TTFB 短。但是在网络特别差的情况下,会大大增加FCP (首屏加载时长) | 可以让初始化请求交给服务端完成,由服务端完成渲染,解决客户端网络不一的情况,FCP 缩短,但是会增加响应时长,TTFB 时长高。每次请求都会触发SSG 渲染。 | 可以让页面生成静态HTML ,在编译时机就可以完成构建,只会触发一次。 | 可以控制HTML 的刷新时长,在指定的时间范围内使用同一个HTML ,时间过后自动重新构建 |
二. 服务端组件和客户端组件
在第一节当中,我们讲到了SSR
,在 NextJs v12
之前,都是通过 getServerSideProps
这个函数来实现服务端渲染,即SSR
。
2.1 水合(Hydration)
SSR
服务端渲染,会将整个组件渲染为HTML
,但是HTML
是没有交互性的。而客户端在渲染HTML
之后,还需要等待JS
下载完毕并且执行,由JS
来赋予HTML
交互性,那么这个阶段就叫做水合。水合过后,内容就会变为可交互性。
那么SSR
有这么几个缺陷:
SSR
渲染,数据的获取必须在组件渲染之前。- 组件的
JS
必须先加载到客户端,才能开始水合。 - 所有组件都必须水合完毕,组件之间才能够进行交互。
因此,一旦有部分组件渲染慢了,就会导致整体的渲染效率降低。不仅如此,SSR
只能适用于页面的初始化加载,对于后续的页面交互、数据修改等操作,SSR
就无作用了。
2.2 Suspense 和 Streaming
上面提到了,服务端只能在获取所有数据后渲染 HTML
,React
只能在下载了所有组件代码后才能进行水合。
为了解决这个问题,就有了 Suspense
组件,它允许你推迟渲染某些内容,直到满足某些条件(例如数据加载完毕)
给个案例如下:
import { Suspense } from 'react'const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));async function Component1() {await sleep(2000)return <h1>Hello Component1</h1>
}async function Component2() {await sleep(3000)return <h1>Hello Component2</h1>
}async function Component3() {await sleep(4000)return <h1>Hello Component3</h1>
}export default function MySuspense() {return (<section style={{ padding: '20px' }}><Suspense fallback={<p>Loading Component1</p>}><Component1 /></Suspense><Suspense fallback={<p>Loading Component2</p>}><Component2 /></Suspense><Suspense fallback={<p>Loading Component3</p>}><Component3 /></Suspense></section>)
}
效果如下:
这种方式我们可以看下请求头:
Transfer-Encoding
的值为 chunked
,表示允许 HTTP
由网页服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分
倘若我们这三个组件都不使用Suspense
封装,效果如下:
整体的效果一目了然。不使用Suspense
封装的情况下,需要等待所有组件都渲染完毕才能完整的展示页面。
而 Suspense
背后的实现技术就叫做Streaming
。即将页面的HTML
拆分多个chunks
,逐步从服务端发送给客户端。有这么几个好处:
- 提前发送到客户端的组件,就可以提前进行水合,那么用户就可以和提前水合完毕的组件进行交互。
- 从页面性能角度来考虑就是:减少
TTFB
和FCP
以及TTI
的时长。有兴趣的可以看下我这篇文章 性能优化 - 前端性能监控和性能指标计算方式
传统的SSR
:
使用Streaming
之后:
那么在NextJs
中有两种实现Streaming
的方式:
- 针对组件级别:使用
Suspense
组件(就上面的案例)。 - 针对页面级别:使用
loading.tsx
。
例如这样的目录结构:
组件1:
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));export default async function Component1() {await sleep(2000)return <h1>Hello Component1</h1>
}
组件2:
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));export default async function Component2() {await sleep(3000)return <h1>Hello Component2</h1>
}
page.tsx
:
import Link from 'next/link'
export default function MySuspense({ children }) {return (<section><nav className="flex items-center justify-center gap-10 text-blue-600 mb-6"><Link href="/suspense/component1">component1</Link><Link href="/suspense/component2">component2</Link></nav>{children}</section>)
}
loading.tsx
:
export default async function loading() {return <h1>loading....</h1>
}
效果如下:
2.3 React Server Components 和 SSR
RSC
(React Server Components
)和 SSR
的区别
RSC
:重点在Components
,即组件。提供了更细粒度的组件渲染方式,可**以在组件中直接获取数据。组件依赖的代码并不会打包到bundle
中。并且只有在客户端请求相关组件的时候才会返回。 **SSR
:重点在Rendering
,即渲染。在服务端将组件渲染成HTML
发送给客户端,因此SSR
需要将组件的所有依赖都打包到bundle
中。
Suspense
以及Streaming
的实现确实能优化我们的页面渲染,将原本只能先获取数据、再渲染水合的传统 SSR
改为渐进式渲染水合 。
但是对于用户需要下载的JS
代码量依旧是没有减少。因此使用RSC
,服务端组件,就能将不必要的代码隐藏到服务器当中。
2.4 服务端组件 VS 客户端组件
在 NextJs
中,组件默认就是服务端组件。这类组件,请求会在服务端执行,最后会将组件渲染成HTML
返回给客户端,例如以下就是一个服务端组件的例子:
const Address = async () => {const res = await fetch('https://jsonplaceholder.typicode.com/posts')const data = (await res.json()).slice(0, 10)console.log(data)return <ul>{data.map(({ title, id }: any) => {return <li key={id}>{title}</li>})}</ul>
}
export default Address
相关的console
打印会在服务端执行:
数据的渲染也会直接在HTML
当中。
那么再来看下对应的客户端组件版本:
- 使用
'use client'
声明。 - 配合
useEffect
钩子函数
'use client'
import { useEffect, useState } from 'react';const Address = () => {const [list, setList] = useState([]);const fetchData = async () => {const res = await fetch('https://jsonplaceholder.typicode.com/todos')const data = (await res.json())setList(data)}useEffect(() => {fetchData()}, [])return <ul>{list.map(({ title, id }: any) => {return <li key={id}>{title}</li>})}</ul>
}export default Address
两者对比的优势如下:
服务端组件 | 客户端组件 | |
---|---|---|
优势 | ① 数据获取更快。 ② 安全(服务端逻辑不会暴露给前端) ③ 缓存(服务端渲染的结果可缓存) ④ 服务端组件的代码不会打包到bundle 中 ⑤ FCP 时长更短 ⑥ 可以使用Streaming ,将渲染工作拆分为chunks ,通过流式传输到客户端,用户可以更早的看到部分页面,而无需等待整个页面渲染完毕。 | ① 交互性更好,可以使用useEffect、useState 等钩子函数。 ② 可以使用浏览器的API |
劣势 | 不可使用useEffect、useState 等钩子函数,也就无法管理状态 | 网络很差的情况下,由客户端完成渲染会导致FCP 特别长 |
运行时机 | 服务端组件运行在构建时和服务端 | 运行在构建时、服务端(生成初始HTML )和客户端(管理DOM ) |
除此之外,还有几个非常重要的点:
- 服务端组件可以直接导入客户端组件,但客户端组件并不能导入服务端组件。
- 服务端组件当导入到客户端组件中,就会被认为是客户端组件。
相关文章:
NextJs 渲染篇 - 什么是CSR、SSR、SSG、ISR 和服务端/客户端组件
NextJs 渲染篇 - 什么是CSR、SSR、SSG、ISR 和服务端/客户端组件 前言一. 什么是CSR、SSR、SSG、ISR1.1 CSR 客户端渲染1.2 SSR 服务端渲染1.3 SSG 静态站点生成① 没有数据请求的页面② 页面内容需要请求数据③ 页面路径需要获取数据 1.4 ISR 增量静态再生1.5 四种渲染方式的对…...
Python 二叉数的实例化及遍历
首先创建一个这样的二叉树,作为我们今天的实例。实例代码在下方。 #创建1个树类型 class TreeNode:def __init__(self,val,leftNone,rightNone):self.valvalself.leftleftself.rightright #实例化类 node1TreeNode(5) node2TreeNode(6) node3TreeNode(7) node4Tre…...
计算 x 的二进制表示中 1 的个数
计算 x 的二进制表示中 1 的个数 代码如下: int func(int x){int countx 0;while (x>0){countx;x x & (x - 1);}return countx;} 完整代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Dat…...
基于Vue的前端瀑布流布局组件的设计与实现
摘要 随着前端技术的不断演进,复杂业务场景和多次迭代后的产品对组件化开发提出了更高的要求。传统的整块应用开发方式已无法满足快速迭代和高效维护的需求。因此,本文将介绍一款基于Vue的瀑布流布局组件,旨在通过组件化开发提升开发效率和降…...
WinSW使用说明
WinSW使用说明 Windows系统下部署多个java程序 场景: 多个java的jar程序,通常来说一个程序使用一个cmd窗口,通过java -jar xxx.jar 命令来运行。这样如果程序多了打开cmd窗口也就多了。 解决: 通过使用WinSW程序,把ja…...
SpringBoot 多模块 多环境 项目 单元测试
环境描述 假设项目中有以下三个yml文件: application.ymlapplication-dev.ymlapplication-prod.yml 假设项目各Module之间依赖关系如下: 其中,D依赖C,C依赖B,B依赖A,D对外提供最终的访问接口 现在要想采…...
网络安全法中的网络安全规定和措施
《中华人民共和国网络安全法》是中国首部全面规范网络空间安全管理的基础性法律,旨在加强网络安全,保障国家安全和社会公共利益,保护公民、法人和其他组织的合法权益,促进互联网的健康发展。以下是该法律中关于网络安全的一些核心…...
一、搭建 Vue3 Admin 项目:从无到有的精彩历程
在前端开发的领域中,Vue3 展现出了强大的魅力,而搭建一个功能丰富的 Vue3 Admin 项目更是充满挑战与乐趣。今天,我将和大家分享我搭建 Vue3 Admin 项目的详细过程,其中用到了一系列重要的依赖包。 首先 让我们开启这个旅程。在确…...
Qt | Qt 资源简介(rcc、qmake)
1、资源系统是一种独立于平台的机制,用于在应用程序的可执行文件中存储二进制文件(前面所讨论的数据都存储在外部设备中)。若应用程序始终需要一组特定的文件(比如图标),则非常有用。 2、资源系统基于 qmake,rcc(Qt 的资源编译器,用于把资源转换为 C++代码)和 QFile …...
对boot项目拆分成cloud项目的笔记
引言:这里我用的是新版本的技术栈 spring-boot-starter-parent >3.2.5 mybatis-spring-boot-starter >3.0.3 mybatis-plus-boot-starter >3.5.5 spring-cloud-dependencies …...
CTF本地靶场搭建——基于阿里云ACR实现动态flag题型的创建
接上文,这篇主要是结合阿里云ACR来实现动态flag题型的创建。 这里顺便也介绍一下阿里云的ACR服务。 阿里云容器镜像服务(简称 ACR)是面向容器镜像、Helm Chart 等符合 OCI 标准的云原生制品安全托管及高效分发平台。 ACR 支持全球同步加速、…...
【面试经典150题】删除有序数组中的重复项
目录 一.删除有序数组中的重复项 一.删除有序数组中的重复项 题目如上图所示,这里非严格递增排序的定义是数字序列,其中相邻的数字可以相等,并且数字之间的差值为1。 这题我们依旧使用迭代器进行遍历,比较当前的数据是否与下一个数…...
太阳能辐射整车综合性能环境试验舱
产品别名 步入式恒温恒湿试验箱、步入式温湿度试验箱、温度试验室、模拟环境试验室、大型恒温恒湿箱、步入式高低温湿热交变试验箱、大型高低温箱、步入式老化箱、恒温恒湿试验房、步入式高低温试验箱. 整车综合性能环境试验舱:整车综合性能环境试验舱:主要用于整车高低温存放…...
JS脚本打包成一个 Chrome 扩展(CRX 插件)
受这篇博客 如何把CSDN的文章导出为PDF_csdn文章怎么导出-CSDN博客 启发,将 JavaScript 代码打包成一个 Chrome 扩展(CRX 插件)。 步骤: 1.创建必要的文件结构和文件: manifest.jsonbackground.jscontent.js 2.编写…...
js事件对象
js事件对象概念说明 在JavaScript中,事件对象是在事件触发时由浏览器自动创建的一个对象。它包含了与事件相关的信息,例如触发事件的元素、事件类型、鼠标的坐标等。 可以通过事件处理函数的第一个参数来访问事件对象。例如,在一个鼠标点击…...
希捷硬盘怎么恢复数据? 5 个免费希捷数据恢复软件
希捷已迅速成为全球最大的数字存储提供商。许多人选择并使用希捷外置硬盘来存储他们的媒体文件、学校或工作文件以及其他重要数据。有时,希捷硬盘中的数据会丢失。 如果您丢失了希捷硬盘上的数据,请不要惊慌。在专业的希捷数据恢复软件的帮助下…...
Nvidia Jetson/Orin +FPGA+AI大算力边缘计算盒子:京东无人配送机器人
电商巨头京东已选用NVIDIA Jetson AGX Xavier 平台,作为下一代自主配送机器人核心AI算力。 在过去的几十年中,中国占据了全球40%以上的电商交易——每年约为千亿美元。根据麦肯锡全球研究院的数据,这一数字已经高于法国、德国、…...
STM32作业实现(七)OLED显示数据
目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…...
elementui el-tooltip文字提示组件弹出层内容格式换行处理
1、第一种 1.1 效果图 1.2、代码 <template><div class"wrapper"><el-tooltip class"content" effect"dark" placement"top"><div slot"content"><div v-html"getTextBrStr(text)"&…...
Python3 笔记:每天一个函数——str.join()
join() :连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串。 语法:sep.join(seq) 参数说明: sep:分隔符。可以为空。 seq:要连接的元素序列、字符串…...
深入解析Python中的None与null:它们真的不同吗?
标题:深入解析Python中的None与null:它们真的不同吗? 摘要 在Python编程中,None是一个常见的概念,而null则通常与Python之外的语言相关。尽管None和null在某些语言中可以互换使用,但在Python中࿰…...
论文作图之高压缩比导出PDF
笔者使用Adobe Illustrator 2023创建可编辑pdf图,按照默认的导出设置保存pdf文件时,得到的图存储很大。为了解决存储过大且还保留一定编辑功能的问题,作者实践出了一种导出pdf的设置方法。 首先在AI中点击文件->存储为,点击保…...
SpringBoot的启动流程
SpringBoot的启动流程 主要包括初始化配置、创建应用程序上下文、刷新上下文以及通知监听者等步骤。 下面将详细探讨SpringBoot的启动流程,以了解其背后的工作原理和机制: 初始化配置:当main方法被调用时,首先通过类加载器读取cla…...
Kubernetes资源调度策略及实现机制
目录 一、资源调度策略 1.默认调度器(Default Scheduler) 2.自定义调度器(Custom Scheduler) 3.亲和性与反亲和性(Affinity and Anti-Affinity) 4.污点与容忍(Taint and Tolerations&#…...
finetuning大模型准备(基于Mac环境)
为finetuning进行的热身准备,涉及周边的软件工具,方法。 问题1:finetuning过程较长,采用系统自带命令行没有后台,前台被杀后,容易造成训练失败。 解决方法: tmux可以开启后台训练 问题2&…...
js检验一个字符串是否是正确时间格式的工具方法
js检验一个字符串是否是正确时间格式的工具方法 (()> {/*** 检验字符串是否为时间格式* param {String} date 需要检验的时间格式* returns true 为时间格式,false 为非时间格式*/const isTimaFormat (date) > {if(!date) return false;try{const tempTime …...
大型制造业集团IT信息化总体规划方案(65页PPT)
方案介绍: 本大型制造业集团IT信息化总体规划方案旨在通过构建先进、高效、稳定的IT信息化系统,支撑集团各业务领域的运营和管理需求,促进集团整体运营效率和竞争力的提升。通过实施本项目,集团将能够更好地应对市场变化和客户需…...
【LIN】STM32新能源汽车LIN通信实现过程
【LIN】STM32新能源汽车LIN通信实现过程 文章目录 前言一、软件二、接线图三、硬件原理图四、上位机五、PICO示波器串行解码1.软件中的LIN波特率设置-192002.PIC设置3.PIC串行解码 六.引用总结 前言 【电机控制】直流有刷电机、无刷电机汇总——持续更新 使用工具:…...
【LeetCode:575. 分糖果+ 哈希表】
🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…...
全文检索-ElasticSearch
1.基本概念 1.Index索引 动词:相当于MySQL中的insert; 名词:相当于MySQL中的DataBase; 2.Type(类型) 在Index(索引)中,可以定义一个或多个类型 类似于MySQL中的Tab…...
C编程惯用法:深入剖析与实战指南
C编程惯用法:深入剖析与实战指南 在C语言编程的浩瀚海洋中,掌握一些惯用法对于提升代码质量、增强可读性以及降低出错率至关重要。本文将从四个方面、五个方面、六个方面和七个方面,详细剖析C编程中的惯用法,帮助您更好地理解和应…...
MySQL数据表的设计
实际工程中, 对于数据表的设计和创建, 我们遵循以下步骤: 首先确定实体, 找到关键名词, 提取关键信息, 设计表有哪些列, 每一列是什么. (有几个实体, 一般就创建几个表, 一般一个表对应一个实体) 实体之间的关系: 1. 一对一关系 例如: 一个学生, 只能有一个账号; 一个账号只…...
Flutter开发效率提升1000%,Flutter Quick教程之对写好的Widget进行嵌套
通常写代码的时候,我们是先写好外面的Widget,再写里面的Widget。但是,也有的时候,我们写好了一个Widget,但是我们觉得有必要再在外面嵌套一个Widget,这时候应该怎么做呢?(还有其他方…...
2020编程语言排序:探索编程界的热门与趋势
2020编程语言排序:探索编程界的热门与趋势 在数字时代的浪潮中,编程语言作为构建数字世界的基石,其流行度和影响力不容忽视。2020年,各大编程语言在各自的领域里展现出独特的魅力和实力。本文将从四个方面、五个方面、六个方面和…...
提高工作效率的招数
自己的工作效率为啥比别人低,因为不会使用工具,这就是一个大冤种。 1.血泪教训,写代码调用第三方接口的时候已经要打印调用日志,不然扯皮真的难搞。 2.pg 上测试或的时候由于schema 错误mybatis会给你报空指针一样,还…...
css特殊效果和页面布局
特殊效果 圆角边框:div{border-radius: 20px 10px 50px 30px;} 四个属性值按顺时针排列,左上的1/4圆半径为20px,右上10,右下50,左下30。 div{border-radius: 20px;} 四角都为20px。 div{border-radius: 20px 10…...
JavaScript中对象的增删改查
1. 增(添加属性) let obj {}; // 添加一个属性 obj.name John Doe; // 或者使用方括号语法添加属性(这对于动态属性名很有用) let propName age; obj[propName] 30; console.log(obj); // 输出: { name: John Doe, …...
技术周总结 2024.05.27~06.02(java bean冲突 软件工程)
文章目录 一、05.28 周二1.1)问题01:java 引用的jar包中bean名称冲突了,怎么解决?1.2)问题02:使用SparkSession将json字符串转成 DataFrame 二、06.01 周六2.1)问题01:系统架构师考试…...
「前端+鸿蒙」核心技术HTML5+CSS3(八)
1、网站布局详解 网站布局是前端开发中的核心概念之一,它决定了网页的视觉结构和用户浏览的逻辑顺序。以下是几种常见的布局方式及其代码示例: 固定布局: 固定布局通常具有固定的宽度和高度,适用于传统的桌面视图。 <!DOCTYPE html> <html> <head><…...
15届蓝桥杯决赛,java b组,蒟蒻赛时所写的题思路
这次题的数量是10题,初赛是8题,还多了两题,个人感觉java b组的题意还是比较清晰的(不存在读不懂题的情况),但是时间感觉还是不够用,第4题一开始不会写,后面记起来写到结束也没调出来…...
2024蓝桥杯国赛C++研究生组游记+个人题解
Day0 开始复习,过了一遍大部分板子 本来打算再学一遍SAM,但是想到去年考了字符串大题今年应该不会再考了吧。。 过了一遍数据结构和图论,就1点了 两点的时候还没睡着,舍友打游戏好像打到2点过。。 Day1 相当困 第一题&…...
C#WPF数字大屏项目实战07--当日产量
1、第2列布局 第2列分三行,第一行分6列 2、当日产量布局 3、产量数据布局 运行效果 4、计划产量和完成度 运行效果 5、良品率布局 1、添加用户控件 2、用户控件绘制圆 2、使用用户控件 3、运行效果 4、注意点 这三个数值目前是静态的,可以由后台程序项…...
MyBatis源码分析--02:SqlSession建立过程
我们再来看看MyBatis使用流程: InputStream inputStream Resources.getResourceAsStream("myBatis_config.xml"); SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream); SqlSession session sqlSessionFactory.op…...
SOUI Combobox 实现半透明弹出下拉框
SOUI默认情况下combobox的弹出框不是半透明的,这个时候如果背景透明时,滚动条会出现黑色背景,这个时候只需要在在combobox下添加一个子节点 <dropdownStyle translucent"1"></dropdownStyle> 这样一个窗口默认即实现…...
Python 猜数系统 PyQt框架 有GUI界面 (源码在最后)【含Python源码 MX_002期】
一、系统简介 猜数界面是一个基于PyQt框架创建的简单图形用户界面(GUI),用于让用户参与猜数字游戏。简要介绍一下界面的各个部分: 游戏开始按钮:点击此按钮开始游戏。在点击前,需要在文本框中输入参与游戏…...
npm install pubsub-js报错的解决汇总
我在练习谷粒商城P83时,选择分类时触发向后端请求选择分类catId绑定的品牌数据,发现前端控制台报错: "PubSub is not definded",找不到pubsub。 因为缺少pubsub包,所以开始安装此包。 于是在网上一顿搜索猛如虎&…...
nuxt2:自定义指令 / v-xxx / directives / 理解 / 使用方法 / DEMO
一、理解自定义指令 在 vue 中提供了一些对于页面和数据更为方便的输出,这些操作就叫做指令,以 v-xxx 表示,比如 html 页面中的属性 <div v-xxx ></div>。自定义指令很大程度提高了开发效率,提高了工程化水平&#x…...
基础—SQL—DCL(数据控制语言)小结
一、总结 在SQL分类中的DCL语句部分,主要讲到了两个部分的知识。 1、用户管理 用户管理,主要是管理哪些用户可以访问当前 mysql 数据库。 包括:创建用户、修改用户密码以及删除用户 2、权限控制 权限管理,主要是控制我们当前用户…...
一文彻底讲透 PyTorch
节前,我们组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 汇总合集…...
JVM常用概念之锁粗化和循环
1.什么是锁粗化 锁粗化一般指有效地合并几个相邻的锁定块,从而减少锁定开销。如下述代码所示: 锁粗化前代码: synchronized (obj) {// statements 1 } synchronized (obj) {// statements 2 }锁粗化后代码: synchronized (obj)…...