Next.js 的砌体布局
Masonry layout with Next.js
我正在开发一个多页面网站,前端使用 Next.js,后端使用 Strapi。在博客页面上,数据是从数据库中动态获取的。我正在尝试使用 Masonry 在自适应布局中显示此数据。
我遇到的问题是,在第一次加载时,页面在单个垂直列中显示每个网格项目。重新加载时,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
});
}
但是当我第一次到达页面或离开并返回时,元素仍然显示在一列中并需要重新加载。
想出了一个不理想的修复方法,但它有效。
在 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 元素,则重新运行 masonry。
保持开放状态,以防有人能提供更好的长期解决方案。
我正在开发一个多页面网站,前端使用 Next.js,后端使用 Strapi。在博客页面上,数据是从数据库中动态获取的。我正在尝试使用 Masonry 在自适应布局中显示此数据。
我遇到的问题是,在第一次加载时,页面在单个垂直列中显示每个网格项目。重新加载时,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
});
}
但是当我第一次到达页面或离开并返回时,元素仍然显示在一列中并需要重新加载。
想出了一个不理想的修复方法,但它有效。
在 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 元素,则重新运行 masonry。
保持开放状态,以防有人能提供更好的长期解决方案。