प्रतिक्रियाशील JS के साथ अनंत स्क्रॉलिंग


89

मैं रिएक्ट के साथ अनंत स्क्रॉलिंग को लागू करने के तरीकों को देख रहा हूं। मैं प्रतिक्रिया-अनंत-स्क्रॉल भर में आया हूं और इसे अक्षम पाया क्योंकि यह केवल डोम में नोड जोड़ता है और उन्हें हटाता नहीं है। क्या रिएक्ट के साथ कोई सिद्ध समाधान है जो डोम में निरंतर संख्या में नोड्स को जोड़ेगा, हटाएगा और बनाए रखेगा।

यहाँ jsfiddle समस्या है। इस समस्या में, मैं एक समय में DOM में केवल 50 तत्व रखना चाहता हूं। दूसरों को लोड और हटाया जाना चाहिए क्योंकि उपयोगकर्ता ऊपर और नीचे स्क्रॉल करता है। हमने अनुकूलन एल्गोरिदम के कारण रिएक्ट का उपयोग करना शुरू कर दिया है। अब मुझे इस समस्या का हल नहीं मिला। मैं एयरबीएन अनंत जी भर के आया हूं । लेकिन इसे Jquery के साथ लागू किया जाता है। इस एयरबीएनबी अनंत स्क्रॉल का उपयोग करने के लिए, मुझे रिएक्ट ऑप्टिमाइज़ेशन को ढीला करना होगा जो मैं नहीं करना चाहता।

नमूना कोड मैं स्क्रॉल जोड़ना चाहता हूं (यहां मैं सभी आइटम लोड कर रहा हूं। मेरा लक्ष्य एक बार में केवल 50 आइटम लोड करना है)

/** @jsx React.DOM */

var Hello = React.createClass({
    render: function() {
        return (<li>Hello {this.props.name}</li>);
    }
});

var HelloList = React.createClass({ 
     getInitialState: function() {                            
         var numbers =  [];
         for(var i=1;i<10000;i++){
             numbers.push(i);
         }
         return {data:numbers};
     },

    render: function(){
       var response =  this.state.data.map(function(contact){          
          return (<Hello name="World"></Hello>);
        });

        return (<ul>{response}</ul>)
    }
});

React.renderComponent(<HelloList/>, document.getElementById('content'));

मदद की तलाश में ...

जवाबों:


57

मूल रूप से स्क्रॉल करते समय आप तय करना चाहते हैं कि कौन से तत्व दिखाई दे रहे हैं और फिर ऑफ़स्क्रीन तत्वों का प्रतिनिधित्व करने के लिए ऊपर और नीचे एक एकल स्पेसर तत्व के साथ केवल उन तत्वों को प्रदर्शित करने के लिए रेंडर करें।

वीजेक्स ने यहां एक फिडेल बनाया है जिसे आप देख सकते हैं: jsfiddle

स्क्रॉल करने पर यह निष्पादित होता है

scrollState: function(scroll) {
    var visibleStart = Math.floor(scroll / this.state.recordHeight);
    var visibleEnd = Math.min(visibleStart + this.state.recordsPerBody, this.state.total - 1);

    var displayStart = Math.max(0, Math.floor(scroll / this.state.recordHeight) - this.state.recordsPerBody * 1.5);
    var displayEnd = Math.min(displayStart + 4 * this.state.recordsPerBody, this.state.total - 1);

    this.setState({
        visibleStart: visibleStart,
        visibleEnd: visibleEnd,
        displayStart: displayStart,
        displayEnd: displayEnd,
        scroll: scroll
    });
},

और फिर रेंडर फ़ंक्शन रेंज में केवल पंक्तियों को प्रदर्शित करेगा displayStart..displayEnd

आपको ReactJS में भी रुचि हो सकती है : मॉडलिंग द्वि-दिशात्मक अनंत स्क्रॉलिंग


2
यह एक महान तकनीक है ... thx! हालाँकि, यह विफल रहता है जब रिकॉर्डहाइट प्रत्येक पंक्ति के लिए अलग है। मैं उस स्थिति के लिए एक फिक्स के साथ प्रयोग कर रहा हूं। अगर मुझे यह काम करने के लिए मिलता है तो मैं इसे पोस्ट करूँगा।
मलांग

@manalang क्या आपने प्रत्येक पंक्ति के लिए अलग-अलग ऊंचाई के लिए समाधान पाया है?
अपवाद

1
जांच करने के लिए एक अन्य परियोजना अनंत (जेएस) (प्रेरणा के लिए) है। यदि आपके पास गतिशील ऊंचाई तत्व हैं, तो आप एक "पृष्ठ" की अवधारणा बना सकते हैं जो व्यूपोर्ट में तत्वों का एक समूह है। कहें कि 3 तत्व हैं, और तीसरा तत्व सुपर लंबा है और पृष्ठ से दूर है। फिर आप कह सकते हैं, "पेज ऊंचाई" सबसे बड़े 3 तत्वों का आकार है। फिर सबसे छोटे तत्व ऊंचाई का उपयोग करके वर्चुअल नोड्स का निर्माण करें । तो var count = pageHeight / minElementHeight। तो आप 50 तत्वों का निर्माण कर सकते हैं, भले ही केवल 3 का ही प्रतिपादन किया गया हो, लेकिन इससे आपको अच्छा प्रदर्शन मिलेगा।
लांस पोलार्ड

14
फिडल में कुछ भी नहीं दिखता है। बटन उत्पन्न करें, लेकिन और कुछ नहीं।
गरज

3
@ सोफी-एल्परट: क्या jsfiddle को अपडेट करना संभव है? मुझे पता है कि आप व्यस्त होंगे, लेकिन अगर आप इसे अपडेट कर सकते हैं, तो यह मेरे जैसे कई लोगों को लाभान्वित करेगा: डी
जॉन सैमुअल

26

हमारी प्रतिक्रिया अनंत पुस्तकालय देखें:

https://github.com/seatgeek/react-infinite

अपडेट दिसंबर 2016

मैं हाल ही में अपनी कई परियोजनाओं में रिएक्ट-वर्चुअलाइज्ड का उपयोग कर रहा हूं और पाता हूं कि यह अधिकांश उपयोग के मामलों को बेहतर तरीके से कवर करता है। दोनों पुस्तकालय अच्छे हैं, यह ठीक उसी पर निर्भर करता है जो आप देख रहे हैं। उदाहरण के लिए, प्रतिक्रिया-वर्चुअलाइज्ड एक HOC नामक चर ऊंचाई JIT मापने का समर्थन करता है CellMeasurer, उदाहरण के लिए https://bvaughn.github.io/react-virtualized/#/compenders/CellMeasurer

अपडेट नवंबर 2018

प्रतिक्रिया-वर्चुअलाइज्ड से बहुत सारे पाठों को एक ही लेखक से छोटे, तेज, अधिक कुशल प्रतिक्रिया-विंडो लाइब्रेरी में पोर्ट किया गया है ।


@jos: इस लाइब्रेरी का उपयोग करें। जब वे व्यूपोर्ट में दिखाई देंगे, तो वह DOM नोड्स को हटा / जोड़ देगा।
wle8300

14
यह लाइब्रेरी केवल तभी काम करती है जब आप रेंडर करने से पहले अपने तत्वों की ऊंचाइयों को जानते हैं।
द्रेष्का

1
@Druska, तकनीकी रूप से हाँ, हालाँकि आप विंडो का उपयोग स्क्रॉल कंटेनर के रूप में भी कर सकते हैं।
हुसैनक

क्या प्रतिक्रिया-अनंत पुस्तकालय ग्रिड का समर्थन करता है?
user1261710

यह वास्तव में करता है, github.com/bvaughn/react-virtualized/blob/master/docs/Grid.md
Zach

1
import React, { Component } from 'react';
import InfiniteScroll from 'react-infinite-scroller';


const api = {
    baseUrl: '/joblist'
};

class Jobs extends Component {
    constructor(props) {
            super(props);
            this.state = {
                listData: [],
                hasMoreItems: true,
                nextHref: null
        };
    }

    fetchData(){
            var self = this;           
            var url = api.baseUrl;
            if(this.state.nextHref) {
                url = this.state.nextHref;
            }

            fetch(url)
            .then( (response) => {
                return response.json() })   
                    .then( (json) => {
                        var list = self.state.listData;                        
                        json.data.map(data => {
                            list.push(data);
                        });

                        if(json.next_page_url != null) {
                            self.setState({
                                nextHref: resp.next_page_url,
                                listData: list                               
                            });
                        } else {
                            self.setState({
                                hasMoreItems: false
                            });
                        }
                    })
                    .catch(error => console.log('err ' + error));

        }
    }

    componentDidMount() {
       this.fetchData();
    }

    render() {
    const loader = <div className="loader">Loading ...</div>;
    let JobItems; 
    if(this.state.listData){  
        JobItems = this.state.listData.map(Job => {
        return (
            <tr>
                <td>{Job.job_number}</td>
                <td>{Job.title}</td>
                <td>{Job.description}</td>
                <td>{Job.status}</td>
            </tr>
        );
      });
    }
    return (
      <div className="Jobs">
        <div className="container">
            <h2>Jobs List</h2>

            <InfiniteScroll
                pageStart={0}
                loadMore={this.fetchData.bind(this)}
                hasMore={this.state.hasMoreItems}
                loader={loader}>
                <table className="table table-bordered">
                <thead>
                    <tr>
                        <th>Job Number</th>
                        <th>Title</th>
                        <th>Description</th>
                        <th>Status</th>
                    </tr>
                </thead>
                <tbody>
                {JobItems}
                </tbody>
                </table>
            </InfiniteScroll>
        </div>
    </div>
    );
  }

}

export default Jobs;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.