2017-08-16 16 views
26

में एक अतिप्रवाह div के नीचे स्क्रॉल करें मेरे पास max-height और overflow-y: auto के साथ है।प्रतिक्रिया

उपयोगकर्ता पर्याप्त li तत्वों प्रवेश करती है, ul शुरू होता है स्क्रॉल करने के लिए है, लेकिन मैं पिछले li उस में form साथ चाहते हैं हमेशा मौजूद है और उपयोगकर्ता के योग्य बनाना चाहते हैं।

मैं एक scrollToBottom समारोह है कि इस तरह दिखता है को लागू करने की कोशिश की है:

scrollToBottom() { 
    this.formLi.scrollIntoView({ behavior: 'smooth' }); 
} 

लेकिन वह सिर्फ स्क्रीन के शीर्ष तक ul कूद बनाता है और ही दिखाई के रूप में यह में फार्म के साथ li दिखाने चीज़।

क्या इसे पूरा करने का कोई बेहतर तरीका है? उत्तर मुझे लगता है कि थोड़ा बड़ा हो और ReactDOM का उपयोग करें। धन्यवाद!

सीएसएस:

.prompt-box .options-holder { 
    list-style: none; 
    padding: 0; 
    width: 95%; 
    margin: 12px auto; 
    max-height: 600px; 
    overflow-y: auto; 
} 

HTML:

<ul className='options-holder'> 
    { 
     this.state.items.map((item, index) => (
      <li key={item.id} className={`option ${index === 0 ? 'first' : ''}`}> 
       <div className='circle' onClick={this.removeItem} /> 

       <p className='item-text'>{ item.text }</p> 
      </li> 
     )) 
    } 

    <li key={0} className={`option form ${this.state.items.length === 0 ? 'only' : ''}`} ref={el => (this.formLi = el)}> 
     <div className='circle form' /> 

     <form className='new-item-form' onSubmit={this.handleSubmit}> 
      <input 
       autoFocus 
       className='new-item-input' 
       placeholder='Type something and press return...' 
       onChange={this.handleChange} 
       value={this.state.text} 
       ref={(input) => (this.formInput = input)} /> 
     </form> 
    </li> 
</ul> 
+0

इस मामले में, हो सकता है आप उल से बाहर पिछले ली ले जाते हैं, और एक अन्य आवरण –

+0

क्यों मैं ऐसा करने के बजाय सिर्फ उल स्क्रॉल करने के लिए चाहते हो जाएगा जोड़ सकता हूँ? –

उत्तर

1

मैं है एक स्क्रिप्ट है कि मैं अपनी परियोजनाओं में से एक में उपयोग किया है निर्बाध रूप शीर्ष स्क्रॉल करने के लिए, मैं एक छोटे से refactor ऊंचाई स्क्रॉल करने के लिए बनाया आपके div (स्क्रॉल नीचे) का मुझे उम्मीद है कि यह मदद करता है।

scroll.js

function currentYPosition() { 
    if (self.pageYOffset) return self.pageYOffset; 
    if (document.documentElement && document.documentElement.scrollHeight) return document.documentElement.scrollHeight; 
    if (document.body.scrollHeight) return document.body.scrollHeight; 

    return 0; 
} 

function elmYPosition(eID) { 
    let elm = document.getElementById(eID); 
    let y = elm.offsetHeight; 
    let node = elm; 
    while (node.offsetParent && node.offsetParent != document.body) { 
    node = node.offsetParent; 
    y += node.offsetHeight; 
    } 
    return y; 
} 

export default function smoothScroll(eID, string) { 
    let startY = currentYPosition(); 
    let stopY = elmYPosition(eID); 
    let distance = stopY > startY ? stopY - startY : startY - stopY; 
    let speed = Math.round(distance/10); 
    let speedTimeout = 250; 
    if (speed >= 100) speed = 100; 
    if (string) speed = 1; 
    let step = Math.round(distance/25); 
    let leapY = stopY > startY ? startY + step : startY - step; 
    let timer = 0; 
    if (stopY > startY) { 
    for (let i = startY; i < stopY; i += step) { 
     setTimeout('window.scrollTo(0, ' + leapY + ')', timer * speed); 
     leapY += step; 
     if (leapY > stopY) leapY = stopY; 
     timer++; 
    } 
    return; 
    } 
    for (let i = startY; i > stopY; i -= step) { 
    setTimeout('window.scrollTo(0, ' + (leapY) + ')', timer * speed); 
    leapY -= step; 
    if (leapY < stopY){ 
     leapY = stopY; 
    } 
    timer++; 
    } 
} 

आप अपने घटक के अंदर इस आयात करना चाहिए, वहाँ 2 मानकों (अपने तत्व की आईडी इस मामले में, आप रेफरी का उपयोग कर सकते हैं। दूसरा एक है एक स्ट्रिंग है कि मैं स्क्रॉल की गति के इलाज के लिए उपयोग किया है।

import scroll from './your-path/scroll.js'; 
. 
. 
. 
<ul className='options-holder'> 
{ 
    this.state.items.map((item, index) => (
     <li key={item.id} className={`option ${index === 0 ? 'first' : ''}`} ref={el => (this.formLi = el)}> 
      <div className='circle' onClick={this.removeItem} /> 

      <p className='item-text'>{ item.text }</p> 
     </li> 
    )) 
} 

<li key={0} className={`option form ${this.state.items.length === 0 ? 'only' : ''}`} ref={el => (this.formLi = el)}> 
    <div className='circle form' /> 

    <form className='new-item-form' onSubmit={this.handleSubmit}> 
     <input 
      autoFocus 
      className='new-item-input' 
      placeholder='Type something and press return...' 
      onChange={this.handleChange} 
      value={this.state.text} 
      ref={(input) => (this.formInput = input)} /> 
    </form> 
</li> 

आईडीके कि आप इस एलआई को अपने प्रस्तुत करने के अंदर कैसे मैप कर रहे हैं लेकिन आपको सत्यापन करना चाहिए और अगर संपत्ति ओवरफ्लो है तो आपको स्क्रॉल चलाया जाना चाहिए।

आपके घटक के लिए पहला तत्व कूदने का एक उचित उत्तर है, आप पहले तत्व के लिए रेफरी मार रहे हैं, अंतिम नहीं।

संभावित वैकल्पिक हल:

scroll(this.state.items[this.state.items.length - 1]); 

अद्यतन 1: मूल scroll.js की सार, scrolling to the top

+0

धन्यवाद यूरी। स्पष्ट होने के लिए, इसके अंदर 'फॉर्म' के साथ केवल 'li' पर' ref' टैग है। अन्य नहीं। संभावित कामकाज 'रेफरी' के रूप में काम नहीं कर रहा है और न ही 'स्क्रॉल' फ़ंक्शन –

2

लगता है आप एक चैट की तरह इंटरफ़ेस का निर्माण कर रहे हैं।आप <ul> और नीचे की तरह एक अलग div में div.circle-form लपेटकर कोशिश कर सकते हैं:

ul{ 
 
    border:1px solid red; 
 
    height:13em; 
 
    overflow-y:auto; 
 
    position:relative; 
 
} 
 
ul li{ 
 
    border-bottom:1px solid #ddd; 
 
    list-style:none; 
 
    margin-left:0; 
 
    padding:6px; 
 
} 
 

 
.wrapper{ 
 
    background:#eee; 
 
    height:15em; 
 
    position:relative; 
 
} 
 
.circle-form{ 
 
    background:#ddd; 
 
    height:2em; 
 
    padding:3px; 
 
    position:absolute; 
 
    bottom:0; 
 
    left:0; 
 
    right:0; 
 
    z-index:2; 
 
} 
 
.circle-form input[type=text]{ 
 
    padding:8px; 
 
    width:50%; 
 
}
<div class="wrapper"> 
 
    <ul id="list"> 
 
     <li>item</li> 
 
     <li>item</li> 
 
     <li>item</li> 
 
     <li>item</li> 
 
     <li>item</li> 
 
     <li>item</li> 
 
     <li>item</li> 
 
     <li>item</li> 
 
    </ul> 
 
    <div class="circle-form"> 
 
     <input type="text" name="type_here" placeholder="Enter something..." autofocus/> 
 
    </div> 
 
</div>

संपादित

और जावास्क्रिप्ट

के साथ इस सूची में नीचे स्क्रॉल करने के लिए
var list = document.getElementById("list"); 
list.scrollTop = list.offsetHeight; 
+2

है, मैं अपने ऐप में jquery का उपयोग नहीं कर रहा हूं और –

+0

का इरादा नहीं चाहता jquery से वेनिला जावास्क्रिप्ट – William

2

react-scroll लाइब्रेरी का उपयोग करें। हालांकि आपको स्पष्ट रूप से अपने ul की आईडी सेट करनी होगी।

import { animateScroll } from "react-scroll"; 

scrollToBottom() { 
    animateScroll.scrollToBottom({ 
     containerId: "options-holder" 
    }); 
} 

आप सेटस्टेट कॉलबैक पर scrollToBottom पर कॉल कर सकते हैं।

उदाहरण

this.setState({ items: newItems}, this.scrollToBottom); 

के लिए या setTimeout का उपयोग करके

या आप Element को react-scroll से भी सेट कर सकते हैं और एक निश्चित li पर स्क्रॉल कर सकते हैं।

1

बस position:sticky s.t का उपयोग करें। अंतिम सूची आइटम हमेशा दिखाया जाता है।

li:last-child { 
    position:sticky; 
    bottom:0; 
} 

Demo

Caniuse

1

मैं ने वही समस्या थी जब यह घटक है कि एक उपयोगकर्ता आयात से आया है की एक सरणी प्रतिपादन के लिए आया था। मैं काम करने के लिए घटकDidUpdate() फ़ंक्शन का उपयोग कर समाप्त हुआ।

componentDidUpdate() { 
     // I was not using an li but may work to keep your div scrolled to the bottom as li's are getting pushed to the div 
     const objDiv = document.getElementById('div'); 
     objDiv.scrollTop = objDiv.scrollHeight; 
     }