我已经建立了react.js网站的创建-反应-应用程序。但是在生产模式中,存在FOUC,因为样式是在html呈现后加载的。
有什么办法解决这个问题吗?我一直在搜索谷歌的答案,但还没有找到合适的答案。
发布于 2018-06-06 19:01:48
FOUC
FOUC --所谓的非样式内容的Flash可能和许多解决这个问题的尝试一样有问题。
恰到好处
让我们考虑以下路由配置(反应路由器):
...
<PageLayout>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/example' component={Example} />
<Switch>
</PageLayout>
...其中PageLayout是一个简单的特制,包含带有page-layout类的div包装器并返回其子类。
现在,让我们关注基于路由的组件呈现。通常,您会使用作为component支柱的React Compoment。但是在我们的例子中,我们需要动态地获得它,以应用帮助我们避免FOUC的特性。所以我们的代码将如下所示:
import asyncRoute from './asyncRoute'
const Home = asyncRoute(() => import('./Home'))
const Example = asyncRoute(() => import('./Example'))
...
<PageLayout>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/example' component={Example} />
<Switch>
</PageLayout>
...为了澄清这一点,我们还将展示asyncRoute.js模块的外观:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Loader from 'components/Loader'
class AsyncImport extends Component {
static propTypes = {
load: PropTypes.func.isRequired,
children: PropTypes.node.isRequired
}
state = {
component: null
}
toggleFoucClass () {
const root = document.getElementById('react-app')
if (root.hasClass('fouc')) {
root.removeClass('fouc')
} else {
root.addClass('fouc')
}
}
componentWillMount () {
this.toggleFoucClass()
}
componentDidMount () {
this.props.load()
.then((component) => {
setTimeout(() => this.toggleFoucClass(), 0)
this.setState(() => ({
component: component.default
}))
})
}
render () {
return this.props.children(this.state.component)
}
}
const asyncRoute = (importFunc) =>
(props) => (
<AsyncImport load={importFunc}>
{(Component) => {
return Component === null
? <Loader loading />
: <Component {...props} />
}}
</AsyncImport>
)
export default asyncRoute
hasClass、addClass、removeClass是对DOM类属性进行操作的多边形填充。Loader是一个自定义组件,它显示自旋器。
为什么是setTimeout?
仅仅因为我们需要在第二个滴答中移除fouc类。否则,它将在与呈现组件相同的情况下发生。这样就没用了。
正如您在AsyncImport组件中所看到的,我们通过添加fouc类来修改根容器。因此,为了清晰起见,HTML:
<html lang="en">
<head></head>
<body>
<div id="react-app"></div>
</body>
</html>另一个谜团是:
#react-app.fouc
.page-layout *
visibility: hidden在导入特定组件(即:Home、Example)时应用sass。
为什么不display: none?
因为我们希望所有依赖父级宽度、高度或任何其他css规则的组件都能正确地呈现出来。
它是如何工作的?
主要假设是隐藏所有元素,直到compoment准备向我们显示呈现的内容。首先,它激发asyncRoute函数,该函数向我们显示Loader,直到Component挂载和呈现。同时,在AsyncImport中,我们通过在react根DOM元素上使用类fouc来切换内容的可见性。当所有东西加载时,是时候显示所有内容了,所以我们删除这个类。
希望这能帮上忙!
感谢
这个文章,这个动态导入的概念是从反应可加载中提取的(我认为)。
来源
https://stackoverflow.com/questions/50694118
复制相似问题