区别
SSR都应该会比较熟悉,就是服务器在每次请求时动态生成完整的 HTML 页面并发送给客户端。
CSR则是完全在客户端渲染,也就是我们常用的单页应用,服务器只返回一个html壳,里面包含一个div根元素,然后加载js,执行render函数,渲染。
RSC感觉是两者的结合,react18推出的,会将组件分为客户端组件与服务端组件(这里的客户端组件并不是指他的初次渲染会在客户端渲染,他也会在服务端进行一次预渲染)。
RSC的客户端与服务端组件
在next中,默认的情况下 在page与layout中都是默认的服务端组件
服务端组件:可以直接访问node APi,也就意味着可以直接访问数据库,有后端能力,但是他不能访问BOM与DOM,也不能使用hooks,这也意味着他仅仅只能是纯静态的组件。
客户端组件需要在文件的顶部编写 'use client',客户端组件并不是指组件会与单页应用一样,初次渲染在客户端。它也会在服务端进行一次渲染,所以不能直接在组件与函数中访问到DOM与BOM(预渲染不会执行任何副作用函数,state的值会使用初始的state的值),这里对比一下代码,与服务端返回的html与我们最终页面的呈现。
看一下代码rootLayout与
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="zh-CN">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<main className="w-full min-h-screen bg-[var(--background)] overflow-x-hidden">
<NavBar />
{children}
</main>
</body>
</html>
);
}
page代码
"use client";
import { useState, useEffect } from "react";
import { Pagination, Input, } from 'antd';
import { Card } from "@/app/components/article";
const { Search } = Input;
export default function Home() {
const [articles, setArticle] = useState(Array.from({length: 10}, (_,index) =>
({id: index, title: `文章${index}`, content: `文章内容${index}`})))
const [categories, setCategories] = useState(Array.from({length: 10}, (_,index) =>
({id: index, name: `分类${index}`})))
const fetchAll = async () => {
// const res = await getArticles()
// setArticle(res.data)
setArticle(Array.from({length: 10}, (_,index) =>
({id: index, title: `文章test${index}`, content: `文章内容test${index}`})))
}
useEffect(() => {
fetchAll()
}, [])
return (
<div className="flex gap-12 p-32 pt-18 bg-[var(--background)] max-w-full overflow-x-hidden">
<div className="flex-1 flex flex-col gap-8">
{ articles.map((item,index) => <Card key={index} {...item}/>)}
<Pagination />
</div>
<div className="flex w-80 flex-col gap-8">
<div
className="rounded-2xl p-6 border backdrop-blur-md
bg-[var(--background-secondary)] border-[var(--border-primary)]"
style={{ boxShadow: 'var(--shadow-md)' }}
>
<Search placeholder="文章搜索" size="large" />
</div>
<ul
className="rounded-2xl px-6 py-4 flex flex-col gap-2 border backdrop-blur-md
bg-[var(--background-secondary)] border-[var(--border-primary)]"
style={{ boxShadow: 'var(--shadow-md)' }}
>
{ categories.map((item,index) => <li key={index} className="h-8 flex ">{item.name} </li>)}
</ul>
</div>
</div>
);
}
服务端返回的html内容

最终页面的呈现

对于客户端组件与服务端组件的拆分
原则:服务端组件可以包含客户端组件,客户端组件不能包含服务端组件。
服务端组件应该只是纯展示的,没有任何的交互,客户端负责余下的交互部分,感觉服务端组件更像整个页面的layout,
- THE END -
共有 0 条评论