ページナビゲーションのためにスクロールハンドラでNext.js命令型ルーティングAPIを使用しようとしています。ウィンドウにアタッチすると、スクロール位置がリセットされるときに色が「フラッシュ」するという小さな例外があります(前のページの上を移動すると新しいルートの下からスクロールし続ける必要があります。色の遷移はシームレスである必要があります。これは、ブラウザのミリ秒単位でscrollTopが0になっているために不可能と思われます)。コード:Next.jsで奇妙な必須のonScrollルーティング動作(サーバ上のレンダリングのみ)
export default class ScrollOMatic extends Component {
constructor(props) {
super(props)
this.state = {
prevRoute: '',
nextRoute: '',
isEndOfScroll: false
}
binder(this, ['handleScroll'])
}
componentWillMount() {
if (typeof window !== 'undefined') {
console.log(window)
}
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll)
const {
prevRoute,
nextRoute
} = this.props.routeData
this.setState({
prevRoute,
nextRoute
})
Router.prefetch('us')
Router.prefetch('work')
Router.prefetch('services')
Router.prefetch('converse')
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll)
}
handleScroll(e) {
e.preventDefault()
let {
scrollTop,
scrollHeight
} = e.srcElement.scrollingElement
scrollHeight = scrollHeight/2
const scrollTiplier = scrollTop/scrollHeight
if (scrollTop === 0) {
Router.push(this.state.prevRoute)
window.scrollTo(0, scrollHeight - 1, {
duration: 0
})
}
if (scrollTiplier === 1) {
Router.push(this.state.nextRoute)
window.scrollTo(0, 1, {
duration: 0
})
}
}
render() {
return (
<div className = 'scroll-o-matic' >{ this.props.children }</div>
)
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
だから、私は有望と思われる反応-水平スクロールに触発され、独自のスクロール動作、とコンテナを使用しています。しかし、この新しいコードでは奇妙なことが起こります。新しいルートはクライアント側にレンダリングされ、サーバーから新しいルートがフェッチされるとページがリフレッシュされます。 GIFおよびコードを参照してください:
// inspired by react-horizontal-scroll
import { Motion, spring, presets } from 'react-motion'
import raf from 'raf'
import Router from 'next/router'
import { fadeColor, binder } from '../../lib/_utils'
import { setScrollState } from '../../lib/_navRules'
export default class ScrollOMatic extends Component {
constructor (props) {
super(props)
this.state = {
prevRoute: '',
nextRoute: '',
animValues: 0
}
binder(this, ['handleWheel', 'resetMin', 'resetMax', 'navigator', 'canIscroll', 'getLayoutData'])
}
componentDidMount() {
const { prevRoute, nextRoute } = this.props.routeData
this.setState({
prevRoute,
nextRoute
})
const prevRouteName = prevRoute === '/' ? 'index' : prevRoute.replace('/', '')
const nextRouteName = prevRoute === '/' ? 'index' : nextRoute.replace('/', '')
Router.prefetch(prevRouteName)
Router.prefetch(nextRouteName)
}
componentWillReceiveProps (nextProps) {
if (this.props.children !== nextProps.children) { this.resetMin() }
}
shouldComponentUpdate (nextProps, nextState) {
if (true &&
this.calculate.timer !== void 0 &&
this.props.children === nextProps.children &&
this.state.animValues === nextState.animValues) {
return false
}
if (true &&
this.props.children === nextProps.children &&
this.canIscroll() === false) {
return false
}
return true
}
componentDidUpdate() { this.calculate() }
getLayoutData() {
const scrollOMatic = DOM.findDOMNode(this.scrollOMatic)
const scrollTray = DOM.findDOMNode(this.scrollTray)
const max = scrollOMatic.scrollHeight
const win = scrollOMatic.offsetHeight
const currentVal = this.state.animValues
const bounds = -(max - win)
const trayTop = scrollTray.offsetTop
const trayOffsetHeight = scrollTray.offsetHeight
const trayScrollHeight = scrollTray.scrollHeight
const scrollOMaticRect = scrollOMatic.getBoundingClientRect()
const scrollOMaticTop = scrollOMaticRect.top
const scrollOMaticHeight = scrollOMaticRect.height
const scrollOMaticOffsetHeight = scrollOMatic.offsetHeight
return {
currentVal,
bounds,
scrollTray,
trayTop,
trayOffsetHeight,
trayScrollHeight,
scrollOMatic,
scrollOMaticTop,
scrollOMaticHeight,
scrollOMaticOffsetHeight,
scrollOMaticRect
}
}
calculate() {
const layout = this.getLayoutData()
clearTimeout(this.calculate.timer)
this.calculate.timer = setTimeout(() => {
const max = layout.trayScrollHeight
const win = layout.scrollOMaticOffsetHeight
const currentVal = this.state.animValues
const bounds = -(max - win)
if (currentVal >= 1) {
this.resetMin()
} else if (currentVal <= bounds) {
const x = bounds + 1
this.resetMax(x)
}
})
}
resetMin() { this.setState({ animValues: 0 }) }
resetMax (x) { this.setState({ animValues: x }) }
canIscroll() {
const layout = this.getLayoutData()
return layout.trayOffsetTop < layout.scrollOMaticTop ||
layout.trayOffsetHeight > layout.scrollOMaticHeight
}
handleWheel (e) {
e.preventDefault()
const rawData = e.deltaY ? e.deltaY : e.deltaX
const mouseY = Math.floor(rawData)
const animationVal = this.state.animValues
const newAnimationVal = (animationVal + mouseY)
const newAnimationValNeg = (animationVal - mouseY)
if (!this.canIscroll()) return
const layout = this.getLayoutData()
const { currentVal, scrollOMaticHeight, trayScrollHeight } = layout
const isEndOfPage = -(currentVal - scrollOMaticHeight) + 1 === trayScrollHeight
this.navigator()
const scrolling =() => {
this.state.scrollInverted
? this.setState({ animValues: newAnimationValNeg })
: this.setState({ animValues: newAnimationVal })
}
raf(scrolling)
}
navigator() {
const layout = this.getLayoutData()
const { currentVal, scrollOMaticHeight, trayScrollHeight } = layout
const shouldBeNextRoute = -(currentVal - scrollOMaticHeight) + 1 >= trayScrollHeight
// const shouldBePrevRoute = this.state.animValues < 0
if (shouldBeNextRoute) {
Router.push(this.state.nextRoute)
}
// if (shouldBePrevRoute) {
// Router.push(this.state.prevRoute)
// }
}
render() {
const springConfig = presets.noWobble
return (
<div style={{ position: 'relative', width: '100vw', height: '100vh' }} className='scroll-o-matic' onWheel={this.handleWheel}
ref={scrollOMatic => { this.scrollOMatic = scrollOMatic }}>
<Motion style={{ z: spring(this.state.animValues, springConfig) }}>
{ ({ z }) => (
<div className='scroll-tray' ref={(scrollTray) => { this.scrollTray = scrollTray }}
style={{
height: '300vh',
width: '100vw',
// top: '-100vh',
transform: `translate3d(0,${z.toFixed(3)}px,0)`,
willChange: 'transform',
display: 'inline-flex',
position: 'absolute'
}}>
{ this.props.children }
</div>
)}
</Motion>
<style jsx>{`
.scroll-o-matic {
background-color: ${this.state.currentColor};
}
`}</style>
</div>
)
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
サーバコード:
const express = require('express')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const port = process.env.PORT || 3000
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
server.use('/static', express.static('static'))
server.get('/', (req, res) => {
return app.render(req, res, '/', req.query)
})
server.get('/us', (req, res) => {
return app.render(req, res, '/us', req.query)
})
server.get('/work', (req, res) => {
return app.render(req, res, '/work', req.query)
})
server.get('/services', (req, res) => {
return app.render(req, res, '/services', req.query)
})
server.get('/converse', (req, res) => {
return app.render(req, res, '/converse', req.query)
})
server.get('*', (req, res) => {
return handle(req, res, '/', req.query)
})
server.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
たぶん私は間違いなく次の 'プリフェッチ' を理解し、それはありません先読みしていないようです。私は主になぜサーバー側のページの読み込みが起こっているのか混乱しています。エクスプレスでワイルドカードリクエストハンドラを使用しても、ページはリロードされますが、自分自身にリダイレクトされるため、私は思っていないサーバー構成には問題ありません。
インターネットの欠点は何ですか?