如果想通过专栏的形式查看本次项目实践可以点击查阅Next 图册目实践
有了之前的Next.js 基础铺垫,我们现在就可以进入花瓣
发现页面的功能开发。本文中的代码只列举出关键的内容,进行讲解。更多源码请查阅github.com/rexleimo/re...的v4.0分支进行查阅。
通过之前的栏目学习,梦兽在UI组件库中选择的是微软的Fluent
进行项目实战。本文主要分析在不用浏览器客户端api的情况下,Server Components如何保存状态。
页面分析
通过页面分析,我们发现,在花瓣
发现页中可以区分6个颜色大区域的组件。本文将以蓝色
,橙色
,灰色
区域进行讲解。也就是我们看到的黄色区域。
javascript
// app/page.tsx
// 我们在组件修改成一些代码 具体代码请到上面提到的github地址进行调整
return (
<>
<Header {...searchParams} />
<div className="flex m-3">
<div className="w-auto flex items-center border border-solid border-gray-100 rounded p-2">
<Link>
采集
</Link>
{/* .... */}
</div>
<div className='flex flex-auto justify-center'>
<div className=' grid grid-cols-6 gap-4 ml-4 max-w-[500px]'>
<Link>推荐</Link>
{/* .... */}
</div>
</div>
<div className='w-[180px]'>
<Select>
<option value="1">综合排序</option>
<option value="2">时间排序</option>
</Select>
</div>
</div >
<ImageList />
</>
)
我们看到花瓣页面发现中,发现一个功能,就是点击画板的时候会有一个灰色的状态。在点击中间区域的推荐时候也会有一个黑色的选中状态。
如果现在是开发spa的应用,我们很容易会使用一下js状态库或者useState。但是现在我们使用的是Server Components,这些方法都无法使用,那我们该如何保存状态呢?
状态保存
由于http是没有状态的,我们在没用useState的情况下,浏览器客户端于服务端之间有什么方式进行保留状态呢?
在web应用开发中,我们通常使用cookie来保存状态。
1.cookie
cookie是浏览器提供的一种机制,用于在浏览器和服务器之间传递状态。http协议是无状态的,也就是说,在http协议中,客户端和服务器之间没有维持状态的机制。
但是,cookie是一种机制,它允许在浏览器和服务器之间传递状态。当浏览器向服务器发出请求时,服务器会向浏览器发送一个cookie。浏览器会将cookie保存在本地,并在下次请求时将cookie发送给服务器。
2. http 报文
我们都知道浏览器和服务端就是通过http报文进行通信的,如果我们收到服务端的报文状态,那么我们就可以在下次请求的时候带上这个状态一起发送到服务端。就能实现了状态的保存。
代码改造
这里主要看注解的代码。
typescript
export default async function Home({ searchParams }: {
searchParams: {
query: string,
cate: string,
search: string
}
}) {
// 判断是否点击了采集/画板
const queryClsxName = (query: string) => clsx(
{
'bg-slate-200': searchParams.query === query,
},
'rounded', 'p-1')
// 判断是否点击了 推荐,游戏等
const cateClsxName = (cate: string) => clsx({
'bg-slate-900': searchParams.cate === cate,
'text-white': searchParams.cate === cate
}, 'rounded', 'p-3', 'text-center')
// 点击调整的时候把上一次http协议中参数(searchParams)一起发送到服务端进行ssr html渲染
const queryParamsSet = (newQuery: { [x: string]: string }) => {
const newSearchParams = new URLSearchParams({
query: searchParams.query,
cate: searchParams.cate,
search: searchParams.search,
...newQuery
})
return newSearchParams.toString();
}
return (
<>
<Header {...searchParams} />
<div className="flex m-3">
<div className="w-auto flex items-center border border-solid border-gray-100 rounded p-2">
<Link href={`?${queryParamsSet({ query: 'design' })}`} className={queryClsxName('design')}>
采集
</Link>
<Link href={`?${queryParamsSet({ query: 'boards' })}`} className={queryClsxName('boards')}>
画板
</Link>
</div>
<div className='flex flex-auto justify-center'>
<div className=' grid grid-cols-6 gap-4 ml-4 max-w-[500px]'>
<Link className={cateClsxName('推荐')} href={`?${queryParamsSet({ cate: '推荐' })}`}>推荐</Link>
<Link className={cateClsxName('UI_UX')} href={`?${queryParamsSet({ cate: 'UI_UX' })}`} >UI/UX</Link>
<Link className={cateClsxName('平面')} href={`?${queryParamsSet({ cate: '平面' })}`} >平面</Link>
<Link className={cateClsxName('摄影')} href={`?${queryParamsSet({ cate: '摄影' })}`}>摄影</Link>
<Link className={cateClsxName('游戏')} href={`?${queryParamsSet({ cate: '游戏' })}`} >游戏</Link>
</div>
</div>
<div className='w-[180px]'>
<Select>
<option value="1">综合排序</option>
<option value="2">时间排序</option>
</Select>
</div>
</div >
<ImageList />
</>
)
}
我们现在来看看成果
20230909-223131.gif
感谢你的阅读,期待在下一篇文章中再次见到你!
这里是梦兽编程,本次的代码更新将会放在Github本次项目的Github连接中的V3.0分支中
我的B站视频号更多视频动态。
截屏2023-08-18 00.02.24.png
本文使用 markdown.com.cn 排版