You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js项目中实现isotope-layout布局?

Next.js 中集成 Isotope-Layout 的解决方案

你的报错本质是Next.js 服务端渲染阶段不存在 window 对象,而 Isotope-Layout 依赖浏览器环境的 window,直接导入会触发这个错误。以下是几种可行的解决方法:

方法一:动态导入组件并禁用 SSR

使用 Next.js 内置的 next/dynamic 工具,将 Isotope 相关组件设置为仅客户端渲染:

1. 封装 Isotope 组件

创建 components/IsotopeGrid.tsx:

import { useEffect, useRef, useState } from 'react';
import Isotope from 'isotope-layout';

interface GridItem {
  id: string;
  category: string;
  content: string;
}

const IsotopeGrid = ({ items }: { items: GridItem[] }) => {
  const gridRef = useRef<HTMLDivElement>(null);
  const [isotopeInstance, setIsotopeInstance] = useState<Isotope | null>(null);

  // 初始化 Isotope
  useEffect(() => {
    if (!gridRef.current) return;

    const isotope = new Isotope(gridRef.current, {
      itemSelector: '.grid-item',
      layoutMode: 'masonry',
      gutter: 10 // 可根据需求调整
    });
    setIsotopeInstance(isotope);

    // 组件卸载时销毁实例
    return () => isotope.destroy();
  }, []);

  // 过滤逻辑
  const handleFilter = (category: string) => {
    isotopeInstance?.arrange({
      filter: category === 'all' ? '*' : `.${category}`
    });
  };

  return (
    <>
      <div className="filter-buttons">
        <button onClick={() => handleFilter('all')}>全部</button>
        <button onClick={() => handleFilter('category1')}>分类1</button>
        <button onClick={() => handleFilter('category2')}>分类2</button>
      </div>
      <div ref={gridRef} className="grid-container">
        {items.map(item => (
          <div key={item.id} className={`grid-item ${item.category}`}>
            {item.content}
          </div>
        ))}
      </div>
    </>
  );
};

export default IsotopeGrid;

2. 在页面中动态导入组件

在页面文件(如 pages/isotope.tsx)中使用动态导入:

import dynamic from 'next/dynamic';

// 禁用 SSR,仅在客户端渲染
const IsotopeGrid = dynamic(() => import('../components/IsotopeGrid'), {
  ssr: false,
  loading: () => <div>加载中...</div>
});

const IsotopePage = () => {
  const gridItems = [
    { id: '1', category: 'category1', content: '项目卡片1' },
    { id: '2', category: 'category2', content: '项目卡片2' },
    { id: '3', category: 'category1', content: '项目卡片3' },
    { id: '4', category: 'category2', content: '项目卡片4' }
  ];

  return <IsotopeGrid items={gridItems} />;
};

export default IsotopePage;

方法二:在 useEffect 中动态导入 Isotope

如果不想整个组件禁用 SSR,可以在客户端生命周期钩子中动态加载 Isotope:

import { useEffect, useRef } from 'react';

interface GridItem {
  id: string;
  category: string;
  content: string;
}

const IsotopeGrid = ({ items }: { items: GridItem[] }) => {
  const gridRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const initIsotope = async () => {
      // 仅在客户端环境导入 Isotope
      const Isotope = (await import('isotope-layout')).default;
      if (gridRef.current) {
        const isotope = new Isotope(gridRef.current, {
          itemSelector: '.grid-item',
          layoutMode: 'fitRows'
        });

        return () => isotope.destroy();
      }
    };

    initIsotope();
  }, [items]);

  return (
    <div ref={gridRef} className="grid-container">
      {items.map(item => (
        <div key={item.id} className={`grid-item ${item.category}`}>
          {item.content}
        </div>
      ))}
    </div>
  );
};

export default IsotopeGrid;

额外注意事项

  • 确保添加基础样式,比如给 .grid-container 设置宽度,.grid-item 设置固定宽度,否则 Isotope 布局可能异常。
  • 如果使用 TypeScript,需要安装类型声明:npm install @types/isotope-layout --save-dev

内容的提问来源于stack exchange,提问作者David H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 16:31:16