我被这个问题困了很多天。我正在使用Next.js并且有 3 页。
的categories/[slug].js是使用Next.js提取方法名getServerSideProps即对每个请求运行,并用于在运行时构建动态页面。在categories/[slug].js该动态内容来自CMS从API端点的响应显示在网页上动态内容。动态内容只不过是一个包含 HTML<script />元素的字符串。
注意:要从 CMS 获取内容,我们必须发送一个POST请求,其中CMS包含用户名、密码和内容的页面 slug 等凭据。我正在使用axios库发送一个 post 请求,并且该方法在post.js文件中。
post.js:
import axios from 'axios';
const postCMS = async (slug) => {
const url = `${process.env.CMS_API_URL}/render-page/`;
let pageSlug = slug;
// If the pageSlug is not start with `/`, then create the slug with `/`
if (!pageSlug.startsWith('/')) {
pageSlug = `/${pageSlug}`;
}
const head = {
Accept: 'application/json',
'Content-Type': 'application/json'
};
const data = JSON.stringify({
username: process.env.CMS_API_USERNAME,
password: process.env.CMS_API_PASSWORD,
slug: pageSlug
});
try {
const response = await axios.post(url, data, {
headers: head
});
return response.data;
} catch (e) {
return e;
}
};
export default postCMS;
Run Code Online (Sandbox Code Playgroud)
但是对于categories/[slug].js页面上的呈现内容,我使用Reactjs道具名称危险地SetInnerHTML来呈现所有 HTML,其中还包含<script />JSON 字符串中的元素。
页面/类别/[slug].js:
<div dangerouslySetInnerHTML={{ __html: result.html }} />
Run Code Online (Sandbox Code Playgroud)
根据每个 slug,内容加载良好。但是当我导航到该类别页面时,即pages/categories/index.js.
<Link href="/categories/[slug]" as="/categories/online-cloud-storage">
<a>Online Cloud Storage</a>
</Link>
Run Code Online (Sandbox Code Playgroud)
它有一个<Link />元素,当我点击它时。
动态内容加载正常,但动态内容包含的元素accordion和slider它们不起作用的元素。我觉得<script />这些元素是行不通的。但是当我刷新页面时,它们工作正常。看到这个。
当我像这样设置链接时,它们也能正常工作。
<Link href="/categories/online-cloud-storage" as="/categories/online-cloud-storage">
<a>Online Cloud Storage</a>
</Link>
Run Code Online (Sandbox Code Playgroud)
但是像上面的方法设置链接后,导致点击硬重载页面。但我不想要这个。一切都应该工作。当用户单击类别链接时。
有没有办法解决这个问题?
当您从categories/index.js页面单击时,为什么内容元素不起作用?
代码:
页面/index.js:
import React from 'react';
import Link from 'next/link';
const IndexPage = () => {
return (
<div>
<Link href="/categories">
<a>Categories</a>
</Link>
</div>
);
};
export default IndexPage;
Run Code Online (Sandbox Code Playgroud)
页面/类别/index.js:
import React from 'react';
import Link from 'next/link';
const Categories = () => {
return (
<div>
<Link href="/categories/[slug]" as="/categories/online-cloud-storage">
<a>Online Cloud Storage</a>
</Link>
</div>
);
};
export default Categories;
Run Code Online (Sandbox Code Playgroud)
页面/类别/[slug].js:
import React from 'react';
import Head from 'next/head';
import postCMS from '../../post';
const CategoryPage = ({ result }) => {
return (
<>
<Head>
{result && <link href={result.assets.stylesheets} rel="stylesheet" />}
</Head>
<div>
<h1>Category page CMS Content</h1>
<div dangerouslySetInnerHTML={{ __html: result.html }} />
</div>
</>
);
};
export const getServerSideProps = async (context) => {
const categorySlug = context.query.slug;
const result = await postCMS(categorySlug);
return {
props: {
result
}
};
};
export default CategoryPage;
Run Code Online (Sandbox Code Playgroud)
恕我直言,我认为脚本不正确加载是由于客户端渲染(CSR)和服务器端渲染(SSR)上的脚本错误导入造成的。在这里阅读更多内容,同时也看看这篇有趣的文章。这也可以解释链接组件的有问题的行为。
就您的情况而言,我知道这种行为是由于 CSR 期间对页面及其组件的生命周期进行错误处理造成的,因为许多脚本可能需要在页面导航中正确共享(可能在 SSR 中)。我不知道问题是什么,也没有扩展的专业知识NextJS,但我相信这些脚本应该导入到一个地方,并可能在服务器上呈现,而不是在每个页面上错误导入,错误地让 CSR 来完成工作以非NextJS优化的方式。
建议的方法是为您的应用程序使用自定义Document实现(仅限 SSR),您可以在其中定义脚本。请参阅此处了解更多详细信息。另外,我想您已经为您的应用程序设置了一个自定义应用程序文件,您将在文档中使用它,以用于所有页面通用的 CSR 和 SSR 渲染(有关更多信息,请参阅此 SO 问题)。
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx) {
// ...
}
render() {
return (
<Html>
<Head>
{/*Your head scripts here*/}
</Head>
<body>
<Main />
{/*Your body scripts here*/}
<NextScript />
</body>
</Html>
)
}
}
Run Code Online (Sandbox Code Playgroud)
本Head机组件在后台做了很多工作,以便为脚本、标记等设置内容。我建议您这样做,而不是直接将脚本添加到每个页面中。
| 归档时间: |
|
| 查看次数: |
3912 次 |
| 最近记录: |