我正在使用React Typescript创建一个APP。我尽量避免在可能的情况下使用Jquery。
我需要检测窗口何时滚动到某个点,以便我可以更新标题类。这是如何在Jquery中完成的:
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if(scroll >= 200) {
$(".navbar-default").addClass("dark");
} else {
$(".navbar-default").removeClass("dark");
}
});
我的入口点HTML看起来像这样(缩减)
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<body>
条目tsx文件:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Layout from './views/layout/layout';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { enthusiasm } from './reducers/index';
import { StoreState } from './types/index';
const store = createStore<StoreState>(enthusiasm, {
enthusiasmLevel: 1,
languageName: 'TypeScript',
});
ReactDOM.render(
<Provider store={store}>
<Layout />
</Provider>,
document.getElementById('root') as HTMLElement
);
registerServiceWorker();
复制此类事件的推荐方法是什么?
答案 0 :(得分:1)
请记住更新状态,而不是dom元素。如果要在componentDidMount上添加新的liistener,则还必须删除componentWillUnmount上的侦听器。
componentDidMount: function() {
window.addEventListener('scroll', this.handleScroll);
},
componentWillUnmount: function() {
window.removeEventListener('scroll', this.handleScroll);
},
handleScroll: function(event) {
//your code to handle scroll
},
答案 1 :(得分:0)
我们遇到了类似的问题,我们通过构建具有子功能的组件来解决它,如此
export interface ScrollElementProps {
children?: (isInRange) => any
throttle?: number
maxScroll?: number
minScroll?: number
}
export interface ScrollElementState {
isInRange: boolean
}
export default
class ScrollElement extends React.Component<ScrollElementProps, ScrollElementState> {
static defaultProps: Partial<ScrollElementProps> = {
throttle: 200,
minScroll: 0,
maxScroll: Number.MAX_VALUE
};
state: ScrollElementState = {
isInRange: false
};
private listenToScroll =
_.throttle(this.props.throttle, () => this.scrollListener());
componentWillMount() {
window.addEventListener('scroll', this.listenToScroll);
}
componentDidMount() {
this.listenToScroll();
}
componentWillUnmount() {
window.removeEventListener('scroll', this.listenToScroll);
}
render() {
return this.props.children(this.state.isInRange);
}
private scrollListener() {
this.setState({ isInRange: this.isWithinScrollRange() });
}
private isWithinScrollRange() {
const { minScroll, maxScroll } = this.props;
return _.inRange(minScroll, maxScroll, documentScrollTop());
}
}
然后你可以像这样使用它:
<ScrollElement maxScroll={200}>
{isInRange => (
<NavBar className={isInRange ? 'dark' : ''}/>
)}
</ScrollElement>
答案 2 :(得分:0)
我写了一个小型的React / Typescript解决方案,可以满足您的需求。
打字稿:
interface AppState {
scroller: number;
}
class Application extends React.Component<{}, AppState> {
state = { scroller: 0 };
handleScroll = () => {
this.setState({ scroller: document.documentElement.scrollTop });
};
componentDidMount() {
window.addEventListener("scroll", this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.handleScroll);
}
render() {
return (
<div>
<nav className={this.state.scroller > 200 ? 'dark' : 'normal'}>This is the nav bar (scroller: {this.state.scroller})</nav>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
<p>Lorem ipsum dolor sit Lorem ipsum dolor sit Lorem ipsum dolor sit</p>
</div>
);
}
}
/*
* Render the above component into the div#app
*/
React.render(<Application />, document.getElementById("root"));
HTML:
<div id="root"></app>
CSS(Sass):
body
padding: 3rem
background: #333
display: flex
font-family: Helvetica Neue
nav
font-size: 2em
display: inline-block
position: fixed
top: 0
padding: 1rem
nav.dark
background-color: black
color: white
nav.normal
background-color: lightgrey
color: black
p
margin-top: 1em
color: #aaa
width: 300px
在CodePen上尝试: https://codepen.io/anon/pen/oMQRqV
请注意,当滚动超过200时,“ nav”元素的颜色将如何变化。
希望这会有所帮助!