【问题标题】:Masonry layout with Next.js使用 Next.js 进行砌体布局
【发布时间】:2019-09-05 13:42:57
【问题描述】:

我正在开发一个多页面网站,前端使用 Next.js,后端使用 Strapi。在博客页面上,数据是从数据库中动态获取的。我正在尝试使用 Masonry 在自适应布局中显示这些数据。

我遇到的问题是,在第一次加载时,页面在单个垂直列中显示每个网格项。重新加载时,砌体布局然后生效,但有一些重叠的项目。在第二次重新加载时,一切都会正确显示,甚至是响应式的。但是,如果我离开页面并返回,它会回到第一格。

这是博客页面的代码:

import React from 'react';
import Layout from '../components/StaticLayout';
import Link from 'next/link';
import fetch from 'isomorphic-unfetch';
import '../../static/styles.min.css';

let Masonry = '';

export default class Blog extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      appIsMounted: false
    }
  }

  static async getInitialProps() {
    const res = await fetch('http://localhost:1337/blogposts');
    const data = await res.json();

    return {
      posts: data
    };
  }

  async componentDidMount() {
    let masonry = await import('masonry-layout');
    this.setState({
      appIsMounted: true
    })
  }

  render() {
    return (
      <Layout>
        <h1 className="blogHeader">Blog</h1>
        {this.state.appIsMounted ? (
          <div className="grid js-masonry" data-masonry-options='{ "itemSelector": ".grid-item", "columnWidth": 400 }'>
            {this.props.posts.map(
              post => (
                <div key={post.id} className="grid-item">
                  <Link href="/p/[id]" as={`/p/${post.id}`}>
                    <img src={`http://localhost:1337${post.Image.url}`} alt={post.Image.name} className="postImage" />
                  </Link>
                  <div className="text">
                    <Link href="/p/[id]" as={`/p/${post.id}`}>
                      <a className="postLink">{post.Title}</a>
                    </Link>
                    <p className="blurb">{post.Content.substring(0, 300) + '...'}</p>
                    <Link href="/p/[id]" as={`/p/${post.id}`}>
                      <button className="viewPost">Read More!</button>
                    </Link>
                  </div>
                </div>
              )
            )}
          </div>
        ) : null}
      </Layout>
    )
  }
}

需要注意的是,StaticLayout 脚本仅确保页眉位于每个页面的顶部。

编辑

所以我已经解决了问题的重叠部分。我没有在 html 中初始化 Masonry,而是在“./static”中添加了一个 js 文件。在我的博客页面上,我添加了以下内容:

import Head from 'next/head'

...

return(
  <Head>
    <script type="text/javascript" src="/static/runMasonry.js"></script>
  </Head>
  ...
)

runMasonry.js 文件如下所示:

window.onload = function () {
  var elem = document.querySelector('.grid');
  var msnry = new Masonry(elem, {
    // options
    itemSelector: '.grid-item',
    columnWidth: 160,
    gutter: 20
  });
}

但是当我第一次到达页面或导航离开并返回时,元素仍然显示在一个列中,需要重新加载。

【问题讨论】:

  • 听起来像是 css 加载问题,你在生产版本中是否有同样的问题?
  • @felixmosh 是的,运行下一次构建和下一次启动后也是同样的问题
  • 你使用next-css吗?您是否看到任何与 css 相关的网络错误?
  • @felixmosh 是的,我正在使用 next-css 将缩小的 css 文件加载到博客页面中。而且我的页面没有网络错误。所有回复都是 200,其中有几个 302

标签: next.js masonry server-side-rendering


【解决方案1】:

想出了一个不理想的修复方法,但它确实有效。

将以下代码添加到 runMasonry.js 文件中:

window.addEventListener("DOMSubtreeModified", function () {
    var elem = document.querySelector('.grid');
    if (elem) {
        var msnry = new Masonry(elem, {
            // options
            itemSelector: '.grid-item',
            columnWidth: 160,
            gutter: 20
        });
    }
});

所以它会检测新页面内容何时加载,如果找到我的 .grid 元素,则重新运行砌体。

保持开放状态,以防有人可以提供更好的长期解决方案。

【讨论】:

    猜你喜欢
    • 2017-05-23
    • 2021-07-19
    • 2013-03-20
    • 2019-11-11
    • 2014-12-13
    • 2021-12-22
    • 2021-03-06
    相关资源
    最近更新 更多