أنا أستخدم react-custom-scrollbar
وأود دمجه مع FixedSizeList
.
لقد راجعت الحل الخاص بهذه المشكلة على react-virtualized
: https://github.com/bvaughn/react-virtualized/issues/692#issuecomment -339393521
لكن الكود يقوم بإلقاء الخطأ: Uncaught TypeError: Cannot read property 'handleScrollEvent' of undefined
عند التمرير ، في هذه الوظيفة:
handleScroll = ({ target }) => {
const { scrollTop, scrollLeft } = target;
const { Grid: grid } = this.List;
grid.handleScrollEvent({ scrollTop, scrollLeft });
}
لقد أضفت ref={ instance => { this.List = instance; } }
على المكوِّن Fixixe <List
.
هذه المكتبة و react-virtualized
هي تطبيقات مختلفة تمامًا. غالبًا ما توفر الأساليب العامة التي تراها في مشكلات react-virtualized
تلميحات مفيدة حول كيفية التعامل مع شيء ما ، لكن تفاصيل التنفيذ المحددة مثل هذه غير قابلة للتطبيق. (في react-virtualized
، يقوم List
بتزيين مكون Grid
. في react-window
، تكون مكونات منفصلة ، من أجل أداء وحجم أفضل.)
لا أعرف ما إذا كان شيء مثل react-custom-scrollbar
سيعمل مع react-window
لأنني لم أجربه مطلقًا. لأكون صادقًا ، إنه ليس شيئًا مهتمًا جدًا بدعمه ، لأنني أعتقد أن أشرطة التمرير المخصصة فكرة سيئة بشكل عام بسبب تأثيرها على الأداء. لذا سأغلق هذه القضية.
لكن يمكننا الاستمرار في الدردشة عليه إذا كانت لديك أسئلة متابعة 😄
سأكتشف شيئًا حول هذا الأمر ، فأنا مهتم باستخدام react-window
لأنه خفيف الوزن ويحل مشكلتي. حتى أنني لا أحب استخدام شريط التمرير المخصص ، ولكنه ليس في يدي ، فنحن بحاجة إلى تصميم مخصص لشريط التمرير.
سأستخدم react-virtualized
في أسوأ الأحوال.
شكرا :)
@ Rahul-Sagore هل انتهى بك الأمر بالحصول على أشرطة تمرير مخصصة تعمل بـ react-window
؟
لا ، لم أحصل على وقت لذلك. بحاجة للتحقق ومعرفة.
لست متأكدًا مما إذا كان bvaughn يوافق على ذلك ، ولكن يبدو أنه يعمل: https://codesandbox.io/s/00nw2w1jv
الطريقة الأفضل هي تمرير Scrollbars
كـ outerElementType
const CustomScrollbars = ({ onScroll, forwardedRef, style, children }) => {
const refSetter = useCallback(scrollbarsRef => {
if (scrollbarsRef) {
forwardedRef(scrollbarsRef.view);
} else {
forwardedRef(null);
}
}, []);
return (
<Scrollbars
ref={refSetter}
style={{ ...style, overflow: "hidden" }}
onScroll={onScroll}
>
{children}
</Scrollbars>
);
};
const CustomScrollbarsVirtualList = React.forwardRef((props, ref) => (
<CustomScrollbars {...props} forwardedRef={ref} />
));
// ...
<FixedSizeList
outerElementType={CustomScrollbarsVirtualList}
{...rest}
/>
أحب عدد الأشياء المتقدمة الممكنة باستخدام outerElementType
أو innerElementType
أحاول اكتشاف موضع التمرير أسفل نافذة التفاعل.
هل هو ممكن؟ هل لديك أي أفكار لذلك؟ أرغب في الحصول على مثال على الشفرات والصناديق .
يجب أن تكون قادرًا على استخدام دعائم المرجع المتاحة لطلب القائمة scrollHeight
rufoot.
لقد حاولت استخدام scrollHeight
في الدعائم. لكنني أعتقد أنه لا توجد خاصية scrollHeight
في ذلك.
bvaughn هل لديك أي فكرة عن ذلك؟
scrollToRow200Auto = () => {
this.listRef.current.scrollToItem(200);
console.log("current position = ", this.listRef.current.props.scrollHeight)
};
المركز الحالي = غير محدد
rufoot شيء مثل هذا https://codesandbox.io/s/4zjwwq98j4 ؟
https://codesandbox.io/embed/jzo2lool2y
عندما تقوم بالتمرير لأسفل في الجزء السفلي من نافذة رد الفعل ، يمكنك رؤية تنبيه واحد.
piecyk لقد جربت الحل الخاص بك بـ outerElementType
وهو بطيء للغاية ، هل جربته؟: D
لقد جربته باستخدام react-scrollbars-custom
. إنه أقل تأخرًا ولكنه لا يزال بطيئًا. هل واجه شخص ما أي مشكلات تتعلق بالتأخر في استخدام أشرطة التمرير المخصصة؟
@ jancama2 لم يقاتلها ، هل يمكنك مشاركة Code Sandbox عندما يصبح بطيئًا؟
rufoot شيء مثل هذا https://codesandbox.io/s/4zjwwq98j4 ؟
أنا أستخدم التنفيذ الخاص بك ولكني أحصل على خطأ يقول أن إعادة التوجيه ريف ليست وظيفة.
المشكلة في تطبيقي التي أحاول حلها هي أن لدي قائمة كبيرة من العناصر وعندما أنقر على أحدها ، سيعيد التطبيق التوجيه إلى مسار آخر لذلك أحتاج إلى تتبع موضع التمرير (ربما يكون في حالة إعادة) و ثم اضبط موضع التمرير بعد تغيير المسار.
هل حاولت دمجها مع InfiniteLoader من react-window-infinite-loader
.
أنا أستخدم react-scrollbars-custom
ويبدو أنه يكسر المحمل اللانهائي :(
رمز بلدي:
<InfiniteLoader isItemLoaded={isItemLoaded} itemCount={items.total} loadMoreItems={loadMoreItems}>
{({
onItemsRendered,
ref,
}: {
onItemsRendered: (props: ListOnItemsRenderedProps) => any;
ref: React.Ref<any>;
}) => (
<List
height={TABLE_HEIGHT}
width={width}
itemCount={items.total}
itemSize={ROW_HEIGHT}
onItemsRendered={onItemsRendered}
itemData={{ items }}
ref={ref}
outerElementType={Scrollbar}
>
{Row}
</List>
)}
</InfiniteLoader>
تحديث: لا أعتقد أنه مرتبط بمكون التمرير اللانهائي. لا يمكنني الحصول عليه للعمل مع شريط التمرير المخصص.
سأكون ممتنًا إذا كان بمقدور شخص ما مشاركة تنفيذ رد فعل التمرير المخصص معي
ranihorev هل تحتاج إلى استخدام هذه الحزمة؟ يستخدم رمز القلم piecyk الذي تمت مشاركته أعلاه أشرطة تمرير مخصصة للتفاعل ويعمل بشكل جيد (باستثناء عند إنشاء مرجع ، والذي لسبب ما يكون فارغًا في الكود الخاص بي)
حسنًا ، أريد أن أسأل مرة أخرى. piecyk أنا أستخدم نموذج الشفرة الخاص بك من الأعلى (حيث أجبت على simjes ). بدلاً من استخدام قائمة ذات حجم ثابت على الرغم من ذلك ، فأنا أستخدم أداة الحجم التلقائي لالتفاف قائمة VariableSizeList وتحديد النوع الخارجي. شيء من هذا القبيل:
<TreeRoot
onDragOver={e => this.onDragOver(e)}
>
<AutoSizer>
{({ height, width }) => (
<List
treeRef={this.props.treeRef}
width={width}
height={height}
itemSize={index => rowHeights[index]}
itemCount={nodeTree.length}
itemData={{
nodeTree,
expandedNodes,
nodesFetching,
nodesFetchingFailed,
selectedNode,
selectedNodeId,
resetRowHeight: this.resetRowHeight,
}}
outerElementType={TreeScrollbar}
outerRef={this.props.outerRef}
onScroll={({ scrollOffset, scrollUpdateWasRequested }) => {
if (scrollUpdateWasRequested) {
console.log('scrollOffset: ', scrollOffset);
}
}}
>
{Node}
</List>
)}
</AutoSizer>
</TreeRoot>
قمت بتطبيق CustomScrollbars و CustomScrollbarsVirtualList كما هو الحال لديك ولكن المرجع دائمًا ما يكون فارغًا. لقد حاولت إنشاء المرجع في المكون الذي أستخدمه في AutoSizer وكذلك في الأصل ولكنه دائمًا فارغ. سأكون ممتنًا حقًا لبعض المساعدة في فهم السبب. كما ذكرت أعلاه ، أحتاج إلى تتبع موضع التمرير وأن أكون قادرًا على ضبطه على تغيير المسار في تطبيقي حتى لا تقفز القائمة مرة أخرى إلى الأعلى.
ChristopherHButler أنا أستخدم بالفعل هذه الحزمة عدة مرات في الكود الخاص بي ، لذلك أفضل الاستمرار في استخدام نفس الحزمة. أنا حل مشابه جدًا ولكنه لا يجلب بيانات جديدة بشكل صحيح
من الصعب حقًا
الفكرة الأساسية هنا هي تعيين المرجع من أشرطة التمرير الخاصة بالتفاعل بحيث تكون نافذة التفاعل
سيعمل AutoSizer أو VariableSizeList مع هذا النهج ، كما في هذا المثال
https://codesandbox.io/s/react-window-custom-scrollbars-t4352
ranihorev هل يمكنك أيضًا مشاركة مثال Code Sandbox؟
piecyk أنشأت مثالًا بسيطًا (
https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-64kzh؟fontsize=14
لقد جربت أيضًا أشكالًا أخرى (على سبيل المثال ، تعيين المرجع ليكون غلاف سكرولر) ولكن لم ينجح ...
شكرا!
ranihorev سيكون هذا الأسلوب هو نفسه بغض النظر عن تنفيذ التمرير المخصص. يحتاجون إلى تعيين مرجع إلى نفس العنصر المسؤول عن التمرير والتعامل مع حدث التمرير هذا.
react-scrollbars-custom
واجهة برمجة تطبيقات أجمل باستخدام نمط الدعائم حتى تتمكن من القيام بشيء مثل https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-pjyxs
لم أفعل أي تنميط ، آمل أن يساعد هذا 👍
piecyk أعمل مع العرض التوضيحي الخاص بك هنا: https://codesandbox.io/s/4zjwwq98j4 . أريد استخدام onScrollStop لإرسال إجراء في redux حتى أتمكن من تعيين موضع التمرير (فكرة من هذا الموضوع: https://github.com/malte-wessel/react-custom-scrollbars/issues/146 ولكن onScrollStart and لا يبدو أن onScrollStop يعمل في الكود الخاص بي أو في العرض التوضيحي الخاص بك. هل تعرف سبب ذلك؟ هل هناك أي طريقة لتمرير الدعائم من القائمة إلى أشرطة التمرير؟
ChristopherHButler أعتقد أن أفضل خيار لك هو استخدام السياق لتمرير الدعائم ، شيء مثل
https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-v2-usi1m
- تم التحرير
إذا قمت بإلغاء تحميل القائمة بأكملها عند تغيير المسار ، فيمكنك إرسال الإجراء ، ثم ، يمكن تخزين Last scrollOffset في المرجع وتحديثه عند كل تغيير في التمرير باستخدام onScroll: function
من VariableSizeList ، فلن تحتاج إلى تمرير الدعائم إلى Scrollbars
pieceyk هذا رائع ، شكرا!
راجع للشغل ، يبدو أن كل ما تحتاجه هو وظيفة onScroll
(التي فاتني) وليس هناك حاجة لإعادة توجيه المرجع على الإطلاق.
https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-99dn1
piecyk آسف ، كان يجب أن
تحديث سريع:
أضفت حالة المكون وقمت بتعيينها على التمرير.
"
تمدد فئة BaseTree المكون {
...
state = {scrollPosition: 0،} ؛
...
listRef = React.createRef () ،
OuterRef = React.createRef () ،
...
يقدم - يجعل {
const {nodes، nodesFetching، nodesFetchingFailed، expandNodes، selectedNode} = this.props؛
إرجاع (
{({height، width}) => ( المرجع = {this.listRef}
className = "قائمة"
OuterRef = {this.outerRef}
ExternalElementType = {TreeScrollbar}
العرض = {العرض}
الارتفاع = {الارتفاع}
onScroll = {({scrollOffset}) => this.setState ({scrollPosition: scrollOffset})}
itemSize = {index => rowHeights [index]}
itemCount = {nodeTree.length}
itemData = {{
nodeTree
العقد الموسعة
العقد
العقد فشل الجلب ،
العقدة المحددة ،
العقدة المحددة ،
resetRowHeight: this.resetRowHeight ،
}}
>
{العقدة}
)}
) ؛
}}
const mapStateToProps = state => ({
scrollPosition: selectors.getTreeScrollPosition (حالة) ،
}) ؛
const mapDispatchToProps = إرسال => ({
setTreeScrollPosition: position => dispatch (Actions.setTreeScrollPosition ({position})) ،
}) ؛
تصدير الاتصال الافتراضي (mapStateToProps ، mapDispatchToProps) (BaseTree) ؛
"
ثم في componentWillUnmout ، أرسل الإجراء لتعيين الموضع في redux مثل هذا:
componentWillUnmount() {
this.props.setTreeScrollPosition(this.state.scrollPosition);
}
مشكلتي الوحيدة الآن هي القدرة على تعيين موضع التمرير عند إعادة تثبيت المكون. حاولت الوصول إلى طريقة scrollTop في هذه القائمة.
this.listRef.current.scrollTop()
لكنني أتلقى خطأ مفاده أنها ليست وظيفة. لست متأكدًا من الخاصية (this.listRef أو this.outerRef) التي يمكنني استخدامها لتعيين موضع التمرير أو بأي طريقة. كنت أفكر في أنه يمكنني تعيينه في المكون المكون من BaseTree على النحو التالي:
componentDidMount() {
const { scrollPosition } = this.props;
if (this.listRef.current) {
// console.log('initializing scroll position to : ', scrollPosition);
this.listRef.current.scrollTop(scrollPosition);
}
}
أي مساعدة للحصول على هذا العمل سيكون موضع تقدير كبير!
تحرير: أنا آسف جدًا ولكن يبدو أن الكود الخاص بي لا يتم تنسيقه بشكل صحيح في هذا المحرر ، لذلك أعتذر عن ذلك :(
ranihorev forward ref
لتفاعل النافذة بحاجة لوظائف مثل scrollTo, scrollToItem
لتعمل
يجب أن يعمل سياق ChristopherHButler تمامًا لهذا الذي تم
يوفر السياق طريقة لتمرير البيانات عبر شجرة المكونات دون الحاجة إلى تمرير الخاصيات يدويًا على كل مستوى.
ولكن كما ذكرنا من قبل ، إذا قمت بإلغاء تحميل المكون بالكامل عند تغيير المسار ، فلا داعي لتمرير الدعائم. لن تخزن scrollPosition
في الحالة لأنك لست بحاجة إليها أثناء التمرير يحدث ، أقل من عمليات إعادة العرض ، قم بتخزينها في المرجع.
onScroll={({ scrollOffset }) => this.setState({ scrollPosition: scrollOffset })}
// to
lastScrollOffsetRef = React.createRef(0);
<List
onScroll={({ scrollOffset }) => {
this.lastScrollOffsetRef.current = scrollOffset
}}
// ...rest
/>
// then in
componentWillUnmount() {
this.props.setTreeScrollPosition(this.lastScrollOffsetRef.current);
}
بالنسبة إلى outerRef
، فهو ليس ضروريًا في حالتك. listRef.current.scrollTo
هي الطريقة الصحيحة التي تريد استخدامها. حسنًا ، فكرتك في استدعاء الطريقة بـ componentDidMount
صحيحة ويجب أن تعمل ،
https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-80zo7
يبدو وكأنه مشكلة توقيت أثناء تعيين المراجع ، ربما يقوم AutoSizer بتأخير عرض القائمة التي تجعل this.listRef.current غير محدد ،
خيار الاختراق هو ، كسر من دورة حياة التفاعل مع setTimeout ، واستدعاء المرجع في العلامة التالية
componentDidMount() {
window.setTimeout(() => {
if (this.listRef.current) {
this.listRef.current.scrollTo(this.props.scrollPosition);
}
}, 0);
}
شكرا جزيلا على بيسيك للمساعدة ، أنا حقا أقدر ذلك :)
شكرا piecyk يبدو أن هذا العمل. هناك وميض طفيف عند التركيب بعد تغيير المسار ولكن يمكنني التعايش معه :) لقد جربت أيضًا اختراقًا آخر وهو استخدام className لتمرير scrollPosition وتعيين scrollTop في refSetter لأشرطة CustomScrollbars:
if (scrollbarsRef) {
forwardedRef(scrollbarsRef.view);
// HACK
scrollbarsRef.scrollTop(className);
}
يبدو انه يشتغل جيدا.
شكرا مرة أخرى على كل ما قدمتموه من مساعدة ، إنه ممتن للغاية !! 🙌🏻
لسوء الحظ ، لا تعمل جميع الأمثلة في هذه المشكلة بشكل صحيح (أحيانًا يتوقف الماوس عن الاستجابة للتمرير).
لكن هذا المثال يعمل بشكل مثالي!
ranihorev سيكون هذا الأسلوب هو نفسه بغض النظر عن تنفيذ التمرير المخصص. يحتاجون إلى تعيين مرجع إلى نفس العنصر المسؤول عن التمرير والتعامل مع حدث التمرير هذا.
react-scrollbars-custom
واجهة برمجة تطبيقات أجمل باستخدام نمط الدعائم حتى تتمكن من القيام بشيء مثل https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-pjyxs
لقد جربته باستخدام
react-scrollbars-custom
. إنه أقل تأخرًا ولكنه لا يزال بطيئًا. هل واجه شخص ما أي مشكلات تتعلق بالتأخر في استخدام أشرطة التمرير المخصصة؟
هل أنجزته؟ ما هو الحل النهائي؟
إذا كان هذا يساعد أي شخص ، فقد تمكنت من جعله يعمل مع OverlayScrollbars . تحتاج فقط إلى تمرير حدث التمرير إلى العنصر المقابل. هذه هي الطريقة:
const Overflow = ({ children, onScroll }) => {
const ofRef = useRef(null);
useEffect(() => {
const el = ofRef.current.osInstance().getElements().viewport;
if (onScroll) el.addEventListener('scroll', onScroll);
return () => {
if (onScroll) el.removeEventListener('scroll', onScroll);
};
}, [onScroll]);
return (
<OverlayScrollbarsComponent
options={options}
ref={ofRef}
>
{children}
</OverlayScrollbarsComponent>
);
};
وبعد ذلك ، في المكون الافتراضي الخاص بك:
<FixedSizeGrid
{...props}
outerElementType={Overflow}
>
أنا أستخدم هذا مع FixedSizeGrid
لكن يجب أن يعمل بنفس الطريقة مع القوائم.
آمل أن يساعد.
التعليق الأكثر فائدة
الطريقة الأفضل هي تمرير
Scrollbars
كـouterElementType
مثال https://codesandbox.io/s/vmr1l0p463