reactjs - 如何阻止 Throttled Scroll 从传播到父级?
问题描述
我有 Scrollable 组件,它可能有可滚动的孩子或大孩子。我想限制onScroll
两个组件中的处理程序,但也能够防止子 onScroll 事件传播到父级。
我的尝试
import React from 'react;
import throttle from 'lodash.throttle'
/*
This component stops the scroll from propagting to the parent
But does not throttle, calls handleScroll way too many times
*/
const UnthrottledSubPage = () => {
const handleScroll = event => {
event.stopPropagation();
console.count(' SubPage: scrolled: ');
console.log(event);
};
return (<div onScroll={handleScroll}>Sub Page</div>);
};
/*
This component throttles the scroll alright...but I have no way
of stopping the scroll event from propagating to a scrollable parent
or grand parent.
*/
const ThrottledSubPageA = () => {
const handleScroll = event => {
event.stopPropagation(); // lineA: Called too late.
console.count(' SubPage: scrolled: ');
console.log(event);
};
return (<div onScroll={throttle(handleScroll, 1000)}>Sub Page</div>);
};
我“怀疑”,这种方法有时在ThrottledSubPageA
s 油门等待时,不会调用 handleScroll 来停止传播,而是调用父滚动,或者在它已经被池化时调用。导致此警告。
警告:出于性能原因,此合成事件被重用。如果您看到此内容,则表示您正在访问已
stopPropagation
发布/无效合成事件的方法。这是一个无操作功能。如果您必须保留原始合成事件,请使用 event.persist()。有关更多信息,请参阅React 事件池。
重现此案例的可运行片段。为日志打开 DevTools
// Scrollable Component, called within a Scrollable Grand Parent (App).
const SubPage = () => {
const handleScroll = event => {
event.stopPropagation();
console.count(' SubPage: scrolled: ');
console.log(event);
};
return (
<div
className="subpage"
style={{ height: '200px' }}
onScroll={throttle(handleScroll, 1000)}
>
<h1>Sub Page</h1>
{/* Lengthy Scrollble Content */}
<div className="content">Content</div>
</div>
);
};
const MainPage = props => {
const { height } = props;
return (
<div className="page" style={{ height }}>
<h1>Main Page</h1>
<SubPage />
</div>
);
};
// Scrollable Component, that has a Scrollable Grand Child.
const App = () => {
const handleScroll = event => {
console.count(' App: scrolled: ');
console.log(event);
};
return (
<section className="app" onScroll={throttle(handleScroll, 1000)}>
<MainPage height="200vh" />
<footer>Footer</footer>
</section>
);
};
ReactDOM.render(<App />, document.getElementById('container'));
/* Styles: Mostly Irrelevant to the question */
body {
padding: 0;
margin: 0;
overflow: hidden;
height: 100vh;
}
.app {
background: #ddd;
width: 100%;
height: 100vh;
overflow-y: scroll;
color: #2b2b2b;
padding: 1rem;
}
.page,
.subpage {
background: aquamarine;
border: solid 1px red;
padding: 2rem;
}
.subpage {
border: solid 1px black;
background: white;
overflow-y: scroll;
}
.content {
height: 200vh;
background: yellow;
}
footer {
background: black;
color: white;
display: block;
width: 100%;
padding: 1rem;
}
<div id="container"></div>
<script src="https://cdn.jsdelivr.net/npm/lodash.throttle@4.1.1/index.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
/*
This component doesn't throttle at all...and behaves like UnthrottledSubPage,
and whatever is within the throttle block is never called.
*/
const ThrottledSubPageB = () => {
const handleScroll = event => {
event.stopPropagation(); // lineA: Called alright.
throttle(()=> {
/* This block is never reached...*/
console.count(' SubPage: scrolled: ');
console.log(event);
}, 1000);
};
return (<div onScroll={handleScroll)}>Sub Page</div>);
};
如果我像上面一样移动油门来包装昂贵的滚动任务,那么油门ThrottledSubPageB
永远不会发生!我再次“认为”(我可能错了)这可能是因为每次滚动都会创建一个新功能,从而导致新的油门,新的等待......永远不会出现。我在日志中看不到它!
问题:,如何确保在滚动时调用节流阀,但仍会在等待中停止下一个滚动,从传播到父级?
解决方案
推荐阅读
- gremlin - 如何在gremlin中进行遍历的交集
- javascript - 如何检查复选框是否被选中?
- python - 在 Python2.7 中应用 Async
- sql - PostgreSQL 随机化外键
- oauth-2.0 - OAuth-2.0/JWT - 关于何时使用范围与角色的指南
- python - Pandas 合并/过滤数据框
- node.js - brew install yvm --without-node 失败
- ruby-on-rails - 如何在 Ruby On Rails 中使用没有模型的 Faker gem?
- python - 包含可滚动画布的框架未占用分配的 Tk 窗口的其余部分
- json - Databricks - 使用 PySpark 从 SQL 列中分解 JSON