在 Next.js 网站中打开一个页面作为叠加层

Posted

技术标签:

【中文标题】在 Next.js 网站中打开一个页面作为叠加层【英文标题】:Open a page in a Next.js website as an overlay 【发布时间】:2021-04-04 04:34:01 【问题描述】:

我有一个可以搜索的网站。我希望用户能够单击搜索结果并在叠加层中打开产品而不是重新加载整个页面,但是我希望 url 栏中的 url 是正确的产品页面,以便用户复制并粘贴它或在新选项卡中打开它,他们将获得产品页面。我还希望后退按钮在这两种情况下都可以使用。

这里有一个更详细的过程说明。

用户导航到位于 /list?keywords=widget 的列表页面 用户点击产品 产品内容在叠加层上以动画形式显示,但列表页面未卸载,它仍位于产品页面下方 URL 栏会更新以反映用户在 /products/123 上,但实际上并未加载产品页面。 如果用户点击后退按钮,则覆盖消失。 如果用户在覆盖打开时点击刷新按钮,他们将获得产品页面的 s-s-r 版本,下面的列表页面不再存在。

起初我以为我可以使用 Next/Router 上的 shallow:true 选项来使其工作,但文档特别指出这仅适用于同一页面导航(使用不同的查询字符串)。

我唯一的想法是,我可以将链接设置为正确的,但在浏览器中劫持它以在历史状态下以纯 javascript 执行某些操作,但我不确定是否可以从中删除 Next Router等式。

为了清楚起见,我不是在寻求产品页面或叠加层本身的帮助,我可以轻松创建在两种情况下显示相同内容的共享组件,特别是我请求帮助的路由和 URL 问题与。

非常感谢任何帮助,即使只是指向正确方向的指针。

【问题讨论】:

你会在这个视频中找到你的答案youtube.com/watch?v=EyjuRCxpf6Y ..祝你好运 尽管有其他有用的答案,但这个视频是其中答案最好的视频。如果您可以通过代码的小示例添加快速答案,我很乐意将其标记为正确并给您积分。 完成。我终于有时间给你一个完整的答案。希望对您有所帮助。 【参考方案1】:

我知道我玩游戏迟到了,但我从 NextJS Documentation 找到了另一种方法,您可能会觉得有用。

在您的情况下,您可以通过这种方式更新您的 next.config 文件

module.exports = 
  async rewrites() 
    return [
      
        source: '/product/:id*',
        destination: '/search', // The :id parameter isn't used here so will be automatically passed in the query
      ,
    ]
  ,

然后在搜索页面中,您可以通过这种方式访问​​产品的 id

const router = useRouter();
const  query  = router;
const productID = query?.id;

根据产品 ID 是否可用,您可以显示或隐藏产品模式/叠加层。

这样做可以减少代码开销,并且您还可以正常使用下一个链接而无需手动更改路线

希望这会有所帮助。干杯!

【讨论】:

【参考方案2】:

这就是我的做法。

您需要创建一个optional catch all route。即:pages/search/[[searchParams]].tsx

import  useRouter  from 'next/router';
import  GetServerSidePropsContext  from 'next';
import  ProductsView, ProductDetailsView  from '@/views';

export async function getServerSideProps(
  params,
: GetServerSidePropsContext) 
  const [productId = null] = (params?.searchParams as string[]) || [];
  return 
    props: 
      productId,
    ,
  ;


interface Props 
  productId?: string;


function SearchProductsPage( productId : Props) 
  const router = useRouter();

  // You could use next/link in your views instead of using next/router
  const onViewDetails = (productDetailsId: string) => 
    router.push(productDetailsId, `product/$productDetailsId`).catch((e) => 
      console.error(e);
    );
  ;
  // Going back to /search will remove the productId and the overlay view will be removed 
  const onClose = () => 
    router.push('/search').catch((e) => 
      console.error(e);
    );
  ;

  // If you have a productId (catch from URL and received via Props)
  // it will render the Product details view which contains the overlay and the product details
  return (
    <>
      <ProductsView onViewDetails=onViewDetails />
      productId && <ProductDetailsView productId=productId onClose=onClose />
    </>
  );


export default SearchProductsPage;

请注意,路由到/product/$productDetailsId 而不是product/$productDetailsId 会报错。因此,使用此代码,您最终会得到像 /search/product/1 这样的 URL,而不是 /product/1

但您可以创建一个单独的页面,即 pages/product/[productId].tsx,它呈现产品详细信息视图,而不是在叠加层中。

【讨论】:

【参考方案3】:

我为你做了一个代码沙盒,希望对你有帮助。

https://codesandbox.io/s/overlay-4qhfb-4qhfb

我们使用了两个 React Hook,一个用于保持状态,一个用于处理事件。我们使用 window.history.pushState 来处理 URL

【讨论】:

谢谢,点击后退按钮时是否可以关闭并重置网址? 是的,您可以添加一个事件监听器并定义您的后退按钮,这将在主要浏览器中得到支持。【参考方案4】:

您可以在推送 URL 时添加状态吗?这样您就可以跟踪以前的 URL。

history.push(
  pathname: PATH_NAME,
  state: 
    from: PREV_URL
  ,
);

【讨论】:

我将不得不对此进行调查。我认为单击后退按钮时这仍会触发 Next 路由器,但如果 history.push 完全独立于 Next 路由器工作,那么这可能会起作用。【参考方案5】:

我不知道任何 Next.js,但您可以将 History.pushState() 与模态结合使用吗?

【讨论】:

以上是关于在 Next.js 网站中打开一个页面作为叠加层的主要内容,如果未能解决你的问题,请参考以下文章

如何在 CodeIgniter 中完全刷新页面?

怎样在ps中对海报图颜色叠加 教你快速实现颜色叠加方法

ViewController 作为 Swift 中 MapView 的叠加层(如 Google 地图应用程序用户界面)

Next.js - 页脚/页眉仅通过 API 加载一次,服务器端

您可以单击的图像叠加层[重复]

Bootstrap 模态叠加另一个模态