React-window: ScrollSyncμ™€μ˜ ν˜Έν™˜μ„±

에 λ§Œλ“  2018λ…„ 11μ›” 08일  Β·  52μ½”λ©˜νŠΈ  Β·  좜처: bvaughn/react-window

상단에 κ³ μ •λœ κ³ μ • 헀더가 μžˆλŠ” κ·Έλ¦¬λ“œλ₯Ό 생성해야 ν•˜λŠ” μ‚¬μš© 사둀가 μžˆμŠ΅λ‹ˆλ‹€. react-virtualizedμ—μ„œ 이것은 두 개의 κ·Έλ¦¬λ“œ ꡬ성 μš”μ†Œ(ν•˜λ‚˜λŠ” ν—€λ”μš©, ν•˜λ‚˜λŠ” κ·Έλ¦¬λ“œ λ°”λ””μš©)λ₯Ό μƒμ„±ν•˜κ³  헀더 κ·Έλ¦¬λ“œμ˜ μˆ˜ν‰ 슀크둀이 메인 κ·Έλ¦¬λ“œμ™€ λ™κΈ°ν™”λ˜λ„λ‘ 슀크둀 μœ„μΉ˜λ₯Ό λ™κΈ°ν™”ν•˜μ—¬ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ³„λ„μ˜ νŒ¨ν‚€μ§€λ‘œ μΆ”κ°€ κΈ°λŠ₯을 κ΅¬μΆ•ν•˜κΈ° μœ„ν•΄ λ²ˆλ“€ 크기와 κ°œλ…μ  λ³΅μž‘μ„± μΈ‘λ©΄μ—μ„œ λ°˜μ‘ 창을 더 κ°€λ³κ²Œ μœ μ§€ν•˜λ €κ³  ν•œλ‹€λŠ” 것을 μ•Œκ³  μžˆμŠ΅λ‹ˆλ‹€. 저도 λ™μ˜ν•˜λŠ” λ°©ν–₯μž…λ‹ˆλ‹€. react-virtualized의 ScrollSync ꡬ성 μš”μ†Œλ₯Ό μΆ”μΆœν•˜κ±°λ‚˜ λ°˜μ‘ μ°½μ—μ„œ μž‘λ™ν•˜λ„λ‘ μ‘°μ •ν•  수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ κ·Έλ ‡κ²Œ ν•˜λ €λ©΄ 헀더 κ·Έλ¦¬λ“œμ˜ 슀크둀 μ˜€ν”„μ…‹μ„ 직접 관리할 수 μžˆλ„λ‘ react-windowκ°€ scrollLeft 및 scrollTop에 λŒ€ν•œ propsλ₯Ό μˆ˜λ½ν•΄μ•Ό ν•©λ‹ˆλ‹€.

μ§€μ›ν•˜κ³ μž ν•˜λŠ” μ‚¬μš© μ‚¬λ‘€μž…λ‹ˆκΉŒ? 그렇지 μ•Šλ‹€λ©΄ 이것을 직접 κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ μ–΄λ–€ λ°©ν–₯으둜 κ°€μ•Όν•˜λŠ”μ§€μ— λŒ€ν•œ 쑰언이 μžˆμŠ΅λ‹ˆκΉŒ?

이 λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ μž‘μ—…ν•΄ μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€. λͺ‡ λ…„ λ™μ•ˆ react-virtualizedλ₯Ό μ‚¬μš©ν•΄ 온 μ‚¬λžŒμœΌλ‘œμ„œ, react-windowλ₯Ό μ‹œμž‘ν•˜λŠ” 것이 κ°„λ‹¨ν•˜κ³  μˆ˜λ™ κ°œμž… 없이 μ–Όλ§ˆλ‚˜ μ„±λŠ₯이 쒋은지 κ°μ‚¬ν•©λ‹ˆλ‹€.

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

그것은 μ™„μ „νžˆ μ˜λ―Έκ°€ μžˆμŠ΅λ‹ˆλ‹€. μ œμ•ˆ κ°μ‚¬ν•©λ‹ˆλ‹€! λ‚˜λŠ” 그것을 μž‘λ™ μ‹œμΌ°κ³  μ‹€μ œλ‘œ μ„€μ •ν•˜κΈ°κ°€ 맀우 μ‰½μŠ΅λ‹ˆλ‹€. λ„ˆλ¬΄ μ‰¬μ›Œμ„œ 독립 μ‹€ν–‰ν˜• νŒ¨ν‚€μ§€λ₯Ό λ³΄μ¦ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ¬Έμ„œμ˜ 예일 μˆ˜λ„ μžˆμ§€λ§Œ 그게 λ‹Ήμ‹ μ˜ 전화라고 μƒκ°ν•©λ‹ˆλ‹€. λ‚˜μ€‘μ— λ‹€λ₯Έ μ‚¬λžŒμ΄ 이 문제λ₯Ό λ°œκ²¬ν•  경우λ₯Ό λŒ€λΉ„ν•˜μ—¬ μž‘μ—… 쀑인 Code Sandbox μ˜ˆμ œμ— λŒ€ν•œ 링크λ₯Ό 여기에 남길 κ²ƒμž…λ‹ˆλ‹€.

https://codesandbox.io/s/y3pyp85zm1

TLDR - 헀더 κ·Έλ¦¬λ“œμ— refλ₯Ό λ„£κ³  λ³Έλ¬Έ κ·Έλ¦¬λ“œμ— λ„£μŠ΅λ‹ˆλ‹€.

onScroll={({ scrollLeft }) => this.headerGrid.current.scrollTo({ scrollLeft })}

λͺ¨λ“  52 λŒ“κΈ€

λ¨Όμ € 쒋은 말씀과 긍정적인 ν”Όλ“œλ°±μ— κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€. μ§€κΈˆκΉŒμ§€ react-windowκ°€ 잘 μž‘λ™ν•˜κ³  μžˆλ‹€λŠ” μ†Œμ‹μ„ λ“€μœΌλ‹ˆ κΈ°μ©λ‹ˆλ‹€!

ScrollSync와 같은 ꡬ성 μš”μ†Œκ°€ react-window에 μ˜μ‘΄ν•˜λŠ” 독립 μ‹€ν–‰ν˜• νŒ¨ν‚€μ§€λ‘œ μΆœμ‹œλ  수 μžˆλ‹€λŠ” μ μ—λŠ” λ™μ˜ν•©λ‹ˆλ‹€.

scroll props에 λŒ€ν•œ κ·€ν•˜μ˜ νŠΉμ • 질문과 κ΄€λ ¨ν•˜μ—¬ 이것은 react-virtualized와 ν•¨κ»˜ μ‚¬μš©ν•œ ν›„ λͺ‡ 가지 μ‹¬κ°ν•œ 단점이 μžˆμŒμ„ κΉ¨λ‹¬μ•˜κΈ° λ•Œλ¬Έμ— ν”„λ‘œμ νŠΈμ— 기꺼이 μ μš©ν•  λ³€κ²½ 사항이 μ•„λ‹™λ‹ˆλ‹€. κΆκΈˆν•œ 점이 있으면 React λΈ”λ‘œκ·Έμ— μ‹€μ œλ‘œ 이에 λŒ€ν•΄ μΌμŠ΅λ‹ˆλ‹€.

https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#anti -pattern-erasing-state-when-props-change

μœ μ‚¬ν•œ 동기화 λ™μž‘μ„ λ‹¬μ„±ν•˜κΈ° μœ„ν•΄ react-windowκ°€ μ œκ³΅ν•˜λŠ” λͺ…λ Ήν˜• 슀크둀 APIλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ†Œν’ˆμ„ μ „λ‹¬ν•˜λŠ” λŒ€μ‹  컀밋 수λͺ… μ£ΌκΈ°μ—μ„œ μ΄λŸ¬ν•œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.

이것이 μ˜λ―Έκ°€ 있기λ₯Ό λ°”λΌμ§€λ§Œ 그렇지 μ•Šμ€ 경우 후속 μ§ˆλ¬Έμ„ 자유둭게 ν•˜μ‹­μ‹œμ˜€!

그것은 μ™„μ „νžˆ μ˜λ―Έκ°€ μžˆμŠ΅λ‹ˆλ‹€. μ œμ•ˆ κ°μ‚¬ν•©λ‹ˆλ‹€! λ‚˜λŠ” 그것을 μž‘λ™ μ‹œμΌ°κ³  μ‹€μ œλ‘œ μ„€μ •ν•˜κΈ°κ°€ 맀우 μ‰½μŠ΅λ‹ˆλ‹€. λ„ˆλ¬΄ μ‰¬μ›Œμ„œ 독립 μ‹€ν–‰ν˜• νŒ¨ν‚€μ§€λ₯Ό λ³΄μ¦ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ¬Έμ„œμ˜ 예일 μˆ˜λ„ μžˆμ§€λ§Œ 그게 λ‹Ήμ‹ μ˜ 전화라고 μƒκ°ν•©λ‹ˆλ‹€. λ‚˜μ€‘μ— λ‹€λ₯Έ μ‚¬λžŒμ΄ 이 문제λ₯Ό λ°œκ²¬ν•  경우λ₯Ό λŒ€λΉ„ν•˜μ—¬ μž‘μ—… 쀑인 Code Sandbox μ˜ˆμ œμ— λŒ€ν•œ 링크λ₯Ό 여기에 남길 κ²ƒμž…λ‹ˆλ‹€.

https://codesandbox.io/s/y3pyp85zm1

TLDR - 헀더 κ·Έλ¦¬λ“œμ— refλ₯Ό λ„£κ³  λ³Έλ¬Έ κ·Έλ¦¬λ“œμ— λ„£μŠ΅λ‹ˆλ‹€.

onScroll={({ scrollLeft }) => this.headerGrid.current.scrollTo({ scrollLeft })}

링크 μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€! 맀우 μ‚¬λ €κΉŠμŠ΅λ‹ˆλ‹€.

2018λ…„ 11μ›” 8일 λͺ©μš”일 μ˜€ν›„ 1:09 Reagan Keeler < [email protected] μž‘μ„±:

그것은 μ™„μ „νžˆ μ˜λ―Έκ°€ μžˆμŠ΅λ‹ˆλ‹€. μ œμ•ˆ κ°μ‚¬ν•©λ‹ˆλ‹€! λ‚˜λŠ” 그것을 μž‘λ™ μ‹œμΌ°κ³ ,
μ‹€μ œλ‘œ μ„€μ •ν•˜κΈ°κ°€ 맀우 μ‰½μŠ΅λ‹ˆλ‹€. λ„ˆλ¬΄ μ‰¬μ›Œμ„œ ν™•μ‹€νžˆ
λ…λ¦½ν˜• νŒ¨ν‚€μ§€λ₯Ό λ³΄μ¦ν•©λ‹ˆλ‹€. λ¬Έμ„œμ˜ 예일 μˆ˜λ„ μžˆμ§€λ§Œ 그게 λ‹Ήμ‹ μ˜ κ²ƒμž…λ‹ˆλ‹€.
μ „ν™”ν•˜λŠ” 것 κ°™μ•„μš”. 여기에 λ‚΄ μž‘μ—… μ½”λ“œ μƒŒλ“œλ°•μŠ€ μ˜ˆμ œμ— λŒ€ν•œ 링크λ₯Ό 남길 κ²ƒμž…λ‹ˆλ‹€.
λ‹€λ₯Έ μ‚¬λžŒμ΄ λ―Έλž˜μ— 이 문제λ₯Ό μš°μ—°νžˆ λ°œκ²¬ν•˜λŠ” 경우λ₯Ό λŒ€λΉ„ν•˜μ—¬.

https://codesandbox.io/s/y3pyp85zm1

TLDR - 헀더 κ·Έλ¦¬λ“œμ— refλ₯Ό λ„£κ³  λ³Έλ¬Έ κ·Έλ¦¬λ“œμ— λ„£μŠ΅λ‹ˆλ‹€.

onScroll={({ scrollLeft }) => this.headerGrid.current.scrollTo({ scrollLeft })}

β€”
μ—΄κΈ°/λ‹«κΈ° μƒνƒœλ₯Ό μˆ˜μ •ν–ˆκΈ° λ•Œλ¬Έμ— 이 λ©”μ‹œμ§€κ°€ ν‘œμ‹œλ©λ‹ˆλ‹€.
이 이메일에 직접 λ‹΅μž₯ν•˜κ³  GitHubμ—μ„œ ν™•μΈν•˜μ„Έμš”.
https://github.com/bvaughn/react-window/issues/86#issuecomment-437156749 ,
λ˜λŠ” μŠ€λ ˆλ“œ μŒμ†Œκ±°
https://github.com/notifications/unsubscribe-auth/AABznTUunzEIs6bVQfVsz7T21L2-Pkkoks5utJ17gaJpZM4YVMd7
.

이것을 μš°μ—°νžˆ λ°œκ²¬ν•œ μ‚¬λžŒμ—κ²ŒλŠ” react-virtualized 슀크둀 λ™κΈ°ν™”λœ 상단/였λ₯Έμͺ½/ν•˜λ‹¨/μ™Όμͺ½ κ³ μ • 슈퍼 κ·Έλ¦¬λ“œκ°€ μžˆμ—ˆλŠ”λ° 이 lib둜 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ν–ˆμŠ΅λ‹ˆλ‹€. μœ„μ˜ μ†”λ£¨μ…˜μ΄ λ‹€λ₯Έ λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ ScrollSync λ₯Ό μ‚¬μš©ν•˜λŠ” 것보닀 더 낫지 μ•Šλ”λΌλ„ μ΅œμ†Œν•œ μ„±λŠ₯이 λ›°μ–΄λ‚˜κ³  고톡이 λœν•˜λ‹€κ³  말할 κ²ƒμž…λ‹ˆλ‹€.

λ˜ν•œ μƒˆλ‘œμš΄ useRef λ°˜μ‘ 후크(https://reactjs.org/docs/hooks-reference.html#useref)와도 μ•„μ£Ό 잘 μ–΄μšΈλ¦½λ‹ˆλ‹€.

const topRef = useRef();
const rightRef = useRef();
const bottomRef = useRef();
const leftRef = useRef();
...
<Grid
  onScroll={({ scrollLeft, scrollTop }) => {
    if (leftRef.current) {
      leftRef.current.scrollTo({ scrollTop });
    }
    if (rightRef.current) {
      rightRef.current.scrollTo({ scrollTop });
    }
    if (topRef.current) {
      topRef.current.scrollTo({ scrollLeft });
    }
    if (bottomRef.current) {
      bottomRef.current.scrollTo({ scrollLeft });
    }
  }}
  ...
/>

멋진! @ranneydλ₯Ό κ³΅μœ ν•΄ μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€!

λ˜ν•œ μƒˆλ‘œμš΄ useRef λ°˜μ‘ 후크(https://reactjs.org/docs/hooks-reference.html#useref)와도 μ•„μ£Ό 잘 μ–΄μšΈλ¦½λ‹ˆλ‹€.

@ranneyd κ°μ‚¬ν•©λ‹ˆλ‹€

μ‹€μ œ 사둀λ₯Ό κ³΅μœ ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

@ranneyd λ‹€μ‹œ ν•œ 번 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€. κ·€ν•˜μ˜ μ ‘κ·Ό 방식을 λ”°λžκ³  슀크둀 동기화가

μŠ€ν¬λ‘€λ°”μ˜ μˆ¨κ²¨μ§„ μ˜€λ²„ν”Œλ‘œλŠ” κ·Έλ¦¬λ“œ 끝 κ·Όμ²˜μ—μ„œ μ •λ ¬ λΆˆλŸ‰μ„ μΌμœΌν‚΅λ‹ˆλ‹€.

gridalignement

이 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 방법에 λŒ€ν•œ μ œμ•ˆ 사항이 μžˆμŠ΅λ‹ˆκΉŒ?

μ½”λ“œμƒŒλ“œλ°•μŠ€ 예

미리 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€

@carlosagsmendes 슀크둀 λ§‰λŒ€ λ•Œλ¬Έμž…λ‹ˆλ‹€. μ™Όμͺ½μ—μ„œ λ†’μ΄μ—μ„œ 슀크둀 λ§‰λŒ€ 크기λ₯Ό λΊ€ 높이λ₯Ό λ§Œλ“­λ‹ˆλ‹€. μž₯치 간에 일관성을 μœ μ§€ν•˜κΈ° μœ„ν•΄ CSSλ₯Ό μ‚¬μš©ν•˜μ—¬ 슀크둀 λ§‰λŒ€ 크기λ₯Ό μˆ˜λ™μœΌλ‘œ ν•˜λ“œ μ½”λ”©ν•©λ‹ˆλ‹€. μ½˜ν…μΈ κ°€ λ„ˆλ¬΄ λ™μ μ΄μ–΄μ„œ 슀크둀 λ§‰λŒ€κ°€ μžˆμ„ μˆ˜λ„ 있고 없을 μˆ˜λ„ μžˆλŠ” 경우 "ν•­λͺ© 수 * ν•­λͺ© 크기 < λ„ˆλΉ„(λͺ¨λ“  값이 λ°”λ‘œ 여기에 μžˆμ–΄μ•Ό 함)"와 같은 μž‘μ—…μ„ μˆ˜ν–‰ν•œ λ‹€μŒ 그에 따라 높이λ₯Ό λ³€κ²½ν•©λ‹ˆλ‹€.

μž₯치 간에 일관성을 μœ μ§€ν•˜κΈ° μœ„ν•΄ CSSλ₯Ό μ‚¬μš©ν•˜μ—¬ 슀크둀 λ§‰λŒ€ 크기λ₯Ό μˆ˜λ™μœΌλ‘œ ν•˜λ“œ μ½”λ”©ν•©λ‹ˆλ‹€.

FWIW dom-helpers νŒ¨ν‚€μ§€μ—λŠ” ν˜„μž¬ μž₯치의 λ„ˆλΉ„λ₯Ό μ•Œλ €μ£ΌλŠ” νŽΈλ¦¬ν•œ scrollbarSize κΈ°λŠ₯ 이 μžˆμŠ΅λ‹ˆλ‹€. ν•˜λ“œ 코딩보닀 λ‚˜μ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

@bvaughn λ„€! λ‚˜λŠ” 그것을 μ–ΈκΈ‰ν•˜λŠ” 것을 μžŠμ—ˆλ‹€. κ·ΈλŸ¬λ‚˜ 그것은 μš°λ¦¬μ—κ²Œ νš¨κ³Όκ°€ μ—†μ—ˆμŠ΅λ‹ˆλ‹€. λ‚΄ 생각에 λ¬Έμ œλŠ” μš°λ¦¬κ°€ 이미 ν•˜λ“œ μ½”λ”©λœ 슀크둀 λ°”λ₯Ό ν•˜κ³  μžˆμ—ˆκ³  그것이 ν˜Όλž€μŠ€λŸ¬μ› λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

μš” κ°μ‚¬ν•©λ‹ˆλ‹€. λ‚˜λŠ” 그것을 μ‹œλ„ ν•  것이닀!

μˆ˜ν‰ VariableSizeListμ—μ„œ μž‘λ™ν•©λ‹ˆκΉŒ? μ‹œλ„ν–ˆμ§€λ§Œ λΈŒλΌμš°μ €κ°€ 멈μΆ₯λ‹ˆλ‹€.

onScroll={({ scrollLeft }) => this.headerGrid.current.scrollTo({ scrollLeft })}

VariableSizeGrid 와 잘 μž‘λ™ν•˜μ§€λ§Œ 슀크둀 μ‹œ 헀더가 μ•½κ°„ λ’€μ²˜μ§‘λ‹ˆλ‹€.

@ajaymore λŠ” 헀더 지연이 μžˆμœΌλ―€λ‘œ Macμ—μ„œ 슀크둀 νœ μ„ μ‚¬μš©ν•  λ•Œ 슀크둀 동기화 λ¬Έμ œκ°€ λ°œμƒν•©λ‹ˆλ‹€. MacOSXμ—λŠ” μŠ€ν¬λ‘€μ„ "λΆ€λ“œλŸ½κ²Œ" λ§Œλ“€κΈ° μœ„ν•΄ λ³΄κ°„ν•˜λŠ” μžμ—° 슀크둀 κΈ°λŠ₯이 λ‚΄μž₯λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. μƒˆλ‘œ κ³ μΉ¨ λΉˆλ„λŠ” μ‹€μ œλ‘œ Chrome의 μ• λ‹ˆλ©”μ΄μ…˜ ν”„λ ˆμž„ 속도보닀 λΉ λ¦…λ‹ˆλ‹€. λ”°λΌμ„œ μŠ€ν¬λ‘€ν•˜λŠ” μš”μ†ŒλŠ” V8/ScrollSyncκ°€ DOM을 μ—…λ°μ΄νŠΈν•  μ‹œκ°„μ„ κ°–κΈ° 전에 μ• λ‹ˆλ©”μ΄μ…˜λ©λ‹ˆλ‹€. 이것은 λ‚΄κ°€ λ³Έ 적이 μ—†λŠ” 기술적 ν•œκ³„μž…λ‹ˆλ‹€.

μž¬λ―ΈμžˆλŠ” 사싀: λΈŒλΌμš°μ €μ—μ„œ 슀크둀 λ§‰λŒ€λ₯Ό μˆ˜λ™μœΌλ‘œ μ‚¬μš©ν•˜λ©΄(예: μž‘μ€ 것을 λŒμ–΄μ„œ ꡬ식 λ°©μ‹μœΌλ‘œ μŠ€ν¬λ‘€ν•˜λŠ” 것과 같이) μ™„μ „νžˆ 잘 μž‘λ™ν•©λ‹ˆλ‹€. 보간 κΈ°λŠ₯은 슀크둀 휠/νŠΈλž™ νŒ¨λ“œ μŠ€μ™€μ΄ν”„μ— λ‚΄μž₯λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

@ajaymore λŠ” 헀더 지연이 μžˆμœΌλ―€λ‘œ Macμ—μ„œ 슀크둀 νœ μ„ μ‚¬μš©ν•  λ•Œ 슀크둀 동기화 λ¬Έμ œκ°€ λ°œμƒν•©λ‹ˆλ‹€. MacOSXμ—λŠ” μŠ€ν¬λ‘€μ„ "λΆ€λ“œλŸ½κ²Œ" λ§Œλ“€κΈ° μœ„ν•΄ λ³΄κ°„ν•˜λŠ” μžμ—° 슀크둀 κΈ°λŠ₯이 λ‚΄μž₯λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. μƒˆλ‘œ κ³ μΉ¨ λΉˆλ„λŠ” μ‹€μ œλ‘œ Chrome의 μ• λ‹ˆλ©”μ΄μ…˜ ν”„λ ˆμž„ 속도보닀 λΉ λ¦…λ‹ˆλ‹€. λ”°λΌμ„œ μŠ€ν¬λ‘€ν•˜λŠ” μš”μ†ŒλŠ” V8/ScrollSyncκ°€ DOM을 μ—…λ°μ΄νŠΈν•  μ‹œκ°„μ„ κ°–κΈ° 전에 μ• λ‹ˆλ©”μ΄μ…˜λ©λ‹ˆλ‹€. 이것은 λ‚΄κ°€ λ³Έ 적이 μ—†λŠ” 기술적 ν•œκ³„μž…λ‹ˆλ‹€.

μž¬λ―ΈμžˆλŠ” 사싀: λΈŒλΌμš°μ €μ—μ„œ 슀크둀 λ§‰λŒ€λ₯Ό μˆ˜λ™μœΌλ‘œ μ‚¬μš©ν•˜λ©΄(예: μž‘μ€ 것을 λŒμ–΄μ„œ ꡬ식 λ°©μ‹μœΌλ‘œ μŠ€ν¬λ‘€ν•˜λŠ” 것과 같이) μ™„μ „νžˆ 잘 μž‘λ™ν•©λ‹ˆλ‹€. 보간 κΈ°λŠ₯은 슀크둀 휠/νŠΈλž™ νŒ¨λ“œ μŠ€μ™€μ΄ν”„μ— λ‚΄μž₯λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

@ranneyd λΉ λ₯Έ λ‹΅λ³€ κ°μ‚¬ν•©λ‹ˆλ‹€. ν•œκ³„λΌλŠ” 점에 λ™μ˜ν•©λ‹ˆλ‹€. λŒ€λΆ€λΆ„μ˜ μž₯μΉ˜μ—μ„œ 잘 μž‘λ™ν•˜λ―€λ‘œ 큰 λ¬Έμ œλŠ” μ•„λ‹™λ‹ˆλ‹€.

@bvaughn position: sticky 가지고 놀아본 적 μžˆλ‚˜μš”? ν•œλ™μ•ˆ μ•ˆμ¨λ΄μ„œ λΈŒλΌμš°μ € 지원이 λ―Έμ•½ν•œκ±Έλ‘œ μ•„λŠ”λ°, μ§€μ›λ˜λŠ” λΈŒλΌμš°μ €μ—μ„œ ν™œμš©ν•  수 μžˆλŠ” 방법이 μ—†μ„κΉŒμš”...

@ajaymore 와 λ™μΌν•œ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€. μ„€λͺ…ν•œ λŒ€λ‘œ μˆ˜λ™ μŠ€ν¬λ‘€μ—μ„œλŠ” μ œλŒ€λ‘œ μž‘λ™ν•¨). PCμ—μ„œ Chrome으둜 ν…ŒμŠ€νŠΈ μ€‘μ΄λ―€λ‘œ Mac만의 λ¬Έμ œλŠ” μ•„λ‹Œ 것 κ°™μŠ΅λ‹ˆλ‹€... λˆ„κ΅°κ°€ 이 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 데 μ„±κ³΅ν–ˆμŠ΅λ‹ˆκΉŒ?

@alonrbar Windows PCμ—μ„œλ„ λ™μΌν•œ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.

μ‹€μ œλ‘œ μ €μ—κ²Œ λ§žλŠ” ν•΄κ²° 방법을 μ°Ύμ•˜μŠ΅λ‹ˆλ‹€.
일반적인 μ•„μ΄λ””μ–΄λŠ” μ›λž˜ κ·Έλ¦¬λ“œμ— μˆ¨μ–΄ onScroll 이벀트λ₯Ό ν›”μΉ˜λŠ” "그림자 κ·Έλ¦¬λ“œ"λ₯Ό λ§Œλ“  λ‹€μŒ 이λ₯Ό μ‚¬μš©ν•˜μ—¬ μ›λž˜ κ·Έλ¦¬λ“œμ™€ ν•„μš”ν•œ λ‹€λ₯Έ κ·Έλ¦¬λ“œλ₯Ό μˆ˜λ™μœΌλ‘œ μŠ€ν¬λ‘€ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. μ„±λŠ₯이 μ•½κ°„ λŠλ €μ§€μ§€λ§Œ λͺ¨λ“  κ·Έλ¦¬λ“œκ°€ 잘 λ™κΈ°ν™”λ˜λ„λ‘ μœ μ§€ν•˜λ―€λ‘œ νŠΈλ ˆμ΄λ“œ μ˜€ν”„λ₯Ό κ³ λ €ν•΄μ•Ό ν•©λ‹ˆλ‹€.

μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

import styled from '@emotion/styled';
import * as React from 'react';
import { VariableSizeGrid, VariableSizeGridProps } from 'react-window';
import { SizeUtils } from '../utils';

export interface SyncableGridProps extends VariableSizeGridProps {
    mainGridRef: React.Ref<VariableSizeGrid>;
    shadowGridRef: React.Ref<VariableSizeGrid>;
    hideVerticalScrollbar?: boolean;
}

export class SyncableGrid extends React.PureComponent<SyncableGridProps> {
    public render() {
        const { height, width } = this.props;
        const {
            onScroll,
            mainGridRef: mainGridRef1,
            shadowGridRef: shadowGridRef1,
            ...mainProps
        } = this.props;
        const {
            children,
            style,
            overscanRowsCount,
            overscanColumnsCount,
            overscanCount,
            useIsScrolling,
            onItemsRendered,
            mainGridRef: mainGridRef2,
            shadowGridRef: shadowGridRef2,
            innerRef,
            outerRef,
            ...shadowProps
        } = this.props;
        return (
            <SyncWrapper
                style={{
                    height,
                    width
                }}
            >
                <MainGrid
                    {...mainProps}
                    style={Object.assign({}, style, {
                        overflowY: 'scroll'
                    })}
                    ref={mainGridRef1}
                />
                <GridShadow
                    {...shadowProps}
                    style={{
                        position: 'absolute',
                        top: 0,
                        left: 0
                    }}
                    ref={shadowGridRef1}
                >
                    {() => null}
                </GridShadow>
            </SyncWrapper>
        );
    }
}

// ---------------- //
//      styles      //
// ---------------- //

const SyncWrapper = styled.div`
    position: relative;
    overflow: hidden;
`;

export interface MainGridProps extends VariableSizeGridProps {
    hideVerticalScrollbar?: boolean;
}

export const MainGrid = styled(VariableSizeGrid) <MainGridProps>`
    overflow-y: scroll;
    box-sizing: content-box;
    ${props => {
        if (!props.hideVerticalScrollbar)
            return '';
        const paddingDir = (props.theme.dir === 'rtl' ? 'padding-left' : 'padding-right');
        return `${paddingDir}: ${SizeUtils.scrollbarWidth}px;`;
    }}
`;

export const GridShadow = styled(MainGrid)`
    opacity: 0;
`;

그런 λ‹€μŒ λ‹€λ₯Έ νŒŒμΌμ—μ„œ:

<SyncableGrid
    mainGridRef={this.firstGridMain}
    shadowGridRef={this.firstGridShadow}
    onScroll={this.handleFirstGridScroll}
    // other props omitted for bravity...
>
   // children omitted for bravity...
</SyncableGrid>
<SyncableGrid
    mainGridRef={this.secondGridMain}
    shadowGridRef={this.secondGridShadow}
    onScroll={this.handleSecondGridScroll}
    // other props omitted for bravity...
>
   // children omitted for bravity...
</SyncableGrid>

private handleFirstGridScroll = (e: GridOnScrollProps) => {
    const { scrollTop, scrollLeft } = e;

    // synchronize self
    if (this.firstGridMain.current) {
        this.firstGridMain.current.scrollTo({ scrollTop, scrollLeft });
    }

    // synchronize other grid
    if (this.secondGridMain.current) {
        this.secondGridMain.current.scrollTo({ scrollTop, scrollLeft });
        this.secondGridShadow.current.scrollTo({ scrollTop, scrollLeft });
    }
}

@alonrbar 맀λ ₯적

그림자 κ²©μžκ°€ μ‹€μ œ 격자 μœ„μ— μžˆλŠ” κ²ƒμ²˜λŸΌ 보이죠? κ·Έλ ‡λ‹€λ©΄ "μ‹€μ œ κ·Έλ¦¬λ“œ"의 클릭 μ΄λ²€νŠΈκ°€ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆκΉŒ? 클릭 이벀트 + x/y μ’Œν‘œλ‘œ μ•½κ°„μ˜ 해킹을 ν•  수 있고 μ–΄λ–»κ²Œλ“  메인 κ·Έλ¦¬λ“œμ— μ μš©ν•  수 μžˆλ‹€κ³  κ°€μ •ν•©λ‹ˆλ‹€.

λ˜ν•œ @barbalex re: Windowsμ—μ„œλ„ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

μ‹€μ œλ‘œλŠ” 크둬 ν”Œλž˜κ·ΈμΌ 수 μžˆμŠ΅λ‹ˆλ‹€. chrome://flags 에 λ‚΄μš©μ΄ μžˆλŠ”μ§€ 확인

이 λ¬Έμ œλŠ” ν™•μ‹€νžˆ λΈŒλΌμš°μ € μ• λ‹ˆλ©”μ΄μ…˜ ν”„λ ˆμž„λ³΄λ‹€ λΉ λ₯΄κ²Œ "λΆ€λ“œλŸ½κ²Œ" μŠ€ν¬λ‘€ν•˜λŠ” 것과 관련이 μžˆλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. μˆœμ „νžˆ μ„±λŠ₯/지연 λ¬Έμ œκ°€ μš°λ €λ˜λŠ” 경우 맀우 기본적인 슀크둀 동기화 κ΅¬ν˜„(ν•œ div의 슀크둀 μ‹œ λ‹€λ₯Έ div의 슀크둀 μœ„μΉ˜ μ„€μ •)을 μ‹œλ„ν•˜κ³  λ™μΌν•œ λ¬Έμ œκ°€ λ°œμƒν•˜λŠ”μ§€ ν™•μΈν•˜μ‹­μ‹œμ˜€. Reactλ₯Ό λ²”μΈμœΌλ‘œ μ œκ±°ν•˜κΈ° μœ„ν•΄ μˆœμˆ˜ν•œ 바닐라 JSμ—μ„œ ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

Ahhh @ranneyd λ‹Ήμ‹  말이 λ§žμ•„μš” 클릭 이벀트λ₯Ό μ°¨λ‹¨ν•©λ‹ˆλ‹€... 그것에 λŒ€ν•΄ 더 생각해야 ν•©λ‹ˆλ‹€...

chrome://flags 의 μŠ€λ ˆλ“œ 슀크둀 κΈ°λŠ₯이 큰 영ν–₯을 λ―ΈμΉœλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. 이 κΈ°λŠ₯을 끄면 마우슀 휠둜 μŠ€ν¬λ‘€ν•˜λŠ” 것이 슀크둀 λ§‰λŒ€λ‘œ μŠ€ν¬λ‘€ν•˜λŠ” κ²ƒλ§ŒνΌ λΆ€λ“œλŸ½κ²Œ λ©λ‹ˆλ‹€.

2019-07-15_00h03_42

@alonrbar 이것은

메인 κ·Έλ¦¬λ“œμ— 슀크둀 ν•Έλ“€λŸ¬λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€. κ±°κΈ°μ—μ„œ e.preventDefault(); λ˜λŠ” μ‹€μ œ μŠ€ν¬λ‘€μ„ λ°©μ§€ν•˜κΈ° μœ„ν•΄ 무언가λ₯Ό μˆ˜ν–‰ν•©λ‹ˆλ‹€. 그런 λ‹€μŒ 이벀트λ₯Ό 보고 μ–Όλ§ˆλ‚˜ 많이 μŠ€ν¬λ‘€λ˜μ—ˆλŠ”μ§€ νŒŒμ•…ν•©λ‹ˆλ‹€. μ΄λŠ” λ‹€λ₯Έ λ™κΈ°ν™”λœ ν•­λͺ©μ„ μ΄λ™ν•˜λŠ” 데 μ‚¬μš©λ˜μ§€λ§Œ λ™μΌν•œ μš”μ†Œλ₯Ό μˆ˜λ™μœΌλ‘œ μŠ€ν¬λ‘€ν•˜λŠ” 데 μ‚¬μš©ν•©λ‹ˆλ‹€. λ”°λΌμ„œ Aλ₯Ό μŠ€ν¬λ‘€ν•˜λŠ” λŒ€μ‹  ν•΄λ‹Ή 정보λ₯Ό μ‚¬μš©ν•˜μ—¬ Bλ₯Ό μŠ€ν¬λ‘€ν•˜λŠ” λŒ€μ‹  Aμ—μ„œ μŠ€ν¬λ‘€μ„ κ°€λ‘œμ±„κ³  μ·¨μ†Œν•œ λ‹€μŒ B와 A 자체λ₯Ό μŠ€ν¬λ‘€ν•˜λŠ” 데 μ‚¬μš©ν•©λ‹ˆλ‹€. 그게 νš¨κ³Όκ°€ μžˆμ„κΉŒμš”?

λ‚˜λŠ” ν…ŒμŠ€νŠΈν•˜κΈ° μœ„ν•΄ 컴퓨터 μ˜†μ— μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ½€ hackyν•˜μ§€λ§Œ λ‚˜λŠ” 일할 수 μžˆμŠ΅λ‹ˆλ‹€. @bvaughn 생각?

@barbalex λ§žμŠ΅λ‹ˆλ‹€. μ €μ—κ²Œλ„ νš¨κ³Όμ μ΄μ§€λ§Œ λͺ¨λ“  μ‚¬μš©μžκ°€ 크둬 ν”Œλž˜κ·Έλ₯Ό 켜고 끌 μˆ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€ πŸ˜”

@ranneyd 방금 μ‚΄νŽ΄λ³΄κ³  μ†ŒμŠ€ μ½”λ“œ( link )둜 μ•½κ°„ λ§Œμ§€μž‘κ±° λ Έμ§€λ§Œ λΆ„λͺ…νžˆ 슀크둀 이벀트λ₯Ό λΉ„ν™œμ„±ν™”ν•  μˆ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€. 슀크둀 이벀트λ₯Ό μœ λ°œν•  수 μžˆλŠ” λͺ¨λ“  마우슀 휠, ν„°μΉ˜ 및 ν‚€λ³΄λ“œ 이벀트λ₯Ό κ°€λ‘œμ±„λŠ” 것뿐 그듀을 λ°©μ§€ν•˜μ‹­μ‹œμ˜€. 링크(SO)μ—λŠ” 이에 λŒ€ν•œ 짧은 μ½”λ“œ μŠ€λ‹ˆνŽ«μ΄ μžˆμ§€λ§Œ 이둜 인해 훨씬 ​​더 ν•΄ν‚Ήλ˜κΈ° λ•Œλ¬Έμ— μ—¬μ „νžˆ 그것에 λŒ€ν•΄ μˆ™κ³ ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€...

@alonrbar 예, μ‚¬μš©μžμ—κ²Œ 이 μž‘μ—…μ„ μˆ˜ν–‰ν•˜λ„λ‘ μš”μ²­ν•˜λ©΄ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ‹œλ„ν•˜λ €λŠ” _do_ 경우 _ν•  수__ μžˆλŠ” 링크: chrome://flags/#disable -threaded-scrolling

@alonrbar μ–΄ 이것은 쒋지 μ•Šμ§€λ§Œ 이미 ν•¨κ»˜ ν•΄ν‚Ήν•  κ·Έλ¦¬λ“œμ— μ μš©ν•˜λŠ” 경우

κ·Έλƒ₯ 슀크둀 휠이죠? ν™”μ‚΄ν‘œ 킀도 λ°œμƒν•©λ‹ˆκΉŒ?

이것은 ν—ˆμš©λ˜λŠ” λ‹΅λ³€μ˜ μŠ€λ‹ˆνŽ«μž…λ‹ˆλ‹€. https://stackoverflow.com/questions/4770025/how-to-disable-scrolling-temporarily

function disableScroll() {
  if (window.addEventListener) // older FF
      window.addEventListener('DOMMouseScroll', preventDefault, false);
  document.addEventListener('wheel', preventDefault, {passive: false}); // Disable scrolling in Chrome
  window.onwheel = preventDefault; // modern standard
  window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
  window.ontouchmove  = preventDefault; // mobile
  document.onkeydown  = preventDefaultForScrollKeys;
}

λ³΄μ‹œλ‹€μ‹œν”Ό μ²˜λ¦¬ν•΄μ•Ό ν•˜λŠ” λͺ‡ 가지 μ΄λ²€νŠΈκ°€ 있고 κ·Έλ ‡κ²Œ ν•¨μœΌλ‘œμ¨ λ°œμƒν•  수 μžˆλŠ” κ²°κ³Όλ₯Ό κ³ λ €ν•΄μ•Ό ν•©λ‹ˆλ‹€.

ν˜„μž¬λ‘œμ„œλŠ” 이 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 데 더 λ§Žμ€ μ‹œκ°„μ„ νˆ¬μžν•  수 μ—†κΈ° λ•Œλ¬Έμ— 가상이 μ•„λ‹Œ μ†”λ£¨μ…˜μ„ μ‚¬μš©ν•˜κΈ°λ‘œ κ²°μ •ν–ˆμŠ΅λ‹ˆλ‹€(μ™„λ²½ν•˜μ§€λŠ” μ•Šμ§€λ§Œ 제 μ‚¬μš© 사둀에 더 적합함). μ—¬κΈ° 와 μ—¬κΈ°μ—μ„œ λ‚΄κ°€ μ‚¬μš©ν•˜λŠ” μ½”λ“œλ₯Ό 찾을 수 μžˆμŠ΅λ‹ˆλ‹€( react-window λž˜ν•‘ν•œ 라이브러리의 μΌλΆ€μž…λ‹ˆλ‹€).

@alonrbar 예 SO μ†”λ£¨μ…˜μ΄ 맀우 ν˜•νŽΈμ—†λ‹€λŠ” 데 λ™μ˜ν•©λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ κ·€ν•˜μ˜ μ†”λ£¨μ…˜μ€ 맀우 ν₯λ―Έλ‘­μŠ΅λ‹ˆλ‹€. λ‚˜λŠ” 그것을 슀슀둜 ν•΄κ²°ν•˜κ³  κ°€μƒν™”λœ ν…Œμ΄λΈ”κ³Ό ν•¨κ»˜ μž‘λ™ν•˜λ„λ‘ λ§Œλ“€ 수 μžˆλŠ”μ§€ ν™•μΈν•˜λ €κ³  ν•©λ‹ˆλ‹€.

@alonrbar κ·Έλž˜μ„œ μ‹€μ œλ‘œ μ ˆλŒ€ μœ„μΉ˜ 지정을 μ‚¬μš©ν•˜λŠ” 비가상화 κ΅¬ν˜„μ„ λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€. μŠ€ν¬λ‘€λ˜λŠ” μœ μΌν•œ 것은 μ™ΈλΆ€ μ»¨ν…Œμ΄λ„ˆμž…λ‹ˆλ‹€. 슀크둀 μ‹œ λ‚΄λΆ€ μš”μ†Œμ˜ μ ˆλŒ€ μœ„μΉ˜λ₯Ό μ§€μ •ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” 상단/μ™Όμͺ½ 값을 μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€. κ·Έλž˜μ„œ λ‚΄κ°€ λ°œκ²¬ν•œ scrollTo λ˜λŠ” scrollTop = ... λŠ” μ €μ—κ²Œ λ§Žμ€ μŠ¬ν””μ„ μ•ˆκ²¨μ£Όμ—ˆμŠ΅λ‹ˆλ‹€. κ·Έ μœ„μ— 슀크둀 λ§‰λŒ€λŠ” 항상 전체 κ·Έλ¦¬λ“œ 외뢀에 μžˆμŠ΅λ‹ˆλ‹€.

λ‚΄κ°€ λ§Œλ“ μ΄ 것은 λͺ¨λ“ λ©΄μ— "κ³ μ • 헀더"λ₯Ό λ™μ μœΌλ‘œ κ°€μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€. 그것은 맀우 거친 예/pocμž…λ‹ˆλ‹€.

λΆ„λͺ…νžˆ μ‹¬κ°ν•œ 문제인 가상화가 λΆ€μ‘±ν•©λ‹ˆλ‹€. λΆˆν–‰νžˆλ„ 이 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” 기본적으둜 μŠ€ν¬λ‘€λ§μ—μ„œ μ‹€ν–‰λ˜κ³  이것은 λ‚΄λΆ€ κ·Έλ¦¬λ“œ μŠ€ν¬λ‘€μ„ μ œκ±°ν•˜κΈ° λ•Œλ¬Έμ— 이 λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ κ·Έλ¦¬λ“œλ₯Ό λž˜ν•‘ν•  수 μžˆλŠ”μ§€ λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. λ‹€μŒ 단계가 무엇인지 ν™•μ‹€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

https://codesandbox.io/embed/non-virtual-scroll-synced-table-ot467

이 λΌμ΄λΈŒλŸ¬λ¦¬μ— μ—°λ£Œλ₯Ό κ³΅κΈ‰ν•˜λŠ” λ™μΌν•œ 가상화 논리가 여기에 적용될 수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

@ranneyd μ•„μ£Ό 멋진 κ΅¬ν˜„μž…λ‹ˆλ‹€!

역동적인 κ·Έλ¦¬λ“œ ꡬ성이 μ’‹μ•„μš” :)

κ·ΈλŸ¬λ‚˜ κ°€μž₯ μ€‘μš”ν•œ 것은 슀크둀링 λŒ€μ‹  μ ˆλŒ€ μœ„μΉ˜ 지정을 μ‚¬μš©ν•˜λŠ” 아이디어가 이 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 열쇠일 수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λ‹€λ₯Έ div λ₯Ό λ„μž…

react-window 의 render λ©”μ†Œλ“œμ— μ—°κ²°ν•  수 μžˆλ‹€λ©΄ 459ν–‰ 이상을 κ΅¬ν˜„μœΌλ‘œ λŒ€μ²΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 그런 λ‹€μŒ onscroll 이벀트λ₯Ό μ—°κ²°ν•˜κ³  ν•„μš”ν•  λ•Œ κ·Έ 효과λ₯Ό λΉ„ν™œμ„±ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€(슀크둀 λ§‰λŒ€λŠ” 계속 μ΄λ™ν•˜μ§€λ§Œ λ‚΄μš©μ΄ λ³€κ²½λ˜μ§€ μ•Šλ„λ‘ μ œμ–΄ν•  수 있음).

@alonrbar κ·Έλž˜μ„œ μ‹€μ œλ‘œ 가상화 μ•Œκ³ λ¦¬μ¦˜μ„ λ‹€μ‹œ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. μ’‹μ§€λŠ” μ•Šμ§€λ§Œ 이 Gridκ°€ μ‹€μ œ 가상화에 λ„λ‹¬ν–ˆμ„ λ•Œ μ†ŒμŠ€ μ½”λ“œλ₯Ό 보면 기본적으둜 λ™μΌν•œ algμž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ‹€μ œλ‘œ μ„±λŠ₯은 μ€€μˆ˜ν•©λ‹ˆλ‹€. 지연 없이 200x200 κ·Έλ¦¬λ“œμ— λ„λ‹¬ν•˜κ³  μ•½κ°„λ§Œ 있으면 500x500에 도달할 수 μžˆμŠ΅λ‹ˆλ‹€. λ‚΄ 상사가 더 이상 이 μž‘μ—…μ„ μˆ˜ν–‰ν•˜λ„λ‘ ν•˜λ©΄ μ œμ•ˆν•œ λŒ€λ‘œ λ Œλ”λ§ λ©”μ„œλ“œ κ΅¬ν˜„μ„ μ‹œλ„ν•  κ²ƒμž…λ‹ˆλ‹€. μ΄λŠ” μ•„λ§ˆλ„ μ‹€μ œλ‘œ 맀우 μ‰¬μšΈ κ²ƒμž…λ‹ˆλ‹€.

λ‚΄κ°€ λ§Œλ“  κ·Έλ¦¬λ“œμ— 관심이 μžˆμœΌμ‹œλ©΄ μ–΄λ”˜κ°€μ— κ²Œμ‹œ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 당신이 그것을 κ°€μ Έ μ™€μ„œμ΄ λΌμ΄λΈŒλŸ¬λ¦¬μ™€ μ—°κ²°ν•˜λ €λ©΄ λ‚΄ μ†λ‹˜μ΄ λ˜μ‹­μ‹œμ˜€ 😏

@ranneyd λ„€, 당신이 λ§Œλ“  가상화 μ†”λ£¨μ…˜μ„ 보고 μ‹ΆμŠ΅λ‹ˆλ‹€. λ‚΄κ°€ 그것을 μ‚¬μš©ν• μ§€λŠ” λͺ¨λ₯΄κ² μ§€λ§Œ ν™•μ‹€νžˆ ν₯미둜울 κ²ƒμž…λ‹ˆλ‹€ :)

λ˜ν•œ 였늘 μ œμ•ˆν•œ λŒ€λ‘œ λ Œλ”λ§ 방법에 λŒ€ν•œ λ³€κ²½ 사항을 κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ κ·€ν•˜μ˜ μ½”λ“œλ₯Ό μ‚¬μš©ν•˜λ €κ³  μ‹œλ„ν–ˆμ§€λ§Œ μ½”λ“œλ₯Ό λ‹€μ‹œ 읽은 ν›„ μƒκ°ν–ˆλ˜ λ°©μ‹μœΌλ‘œ μŠ€ν¬λ‘€λ§μ„ μ‹€μ œλ‘œ μ—°κ²° ν•΄μ œν•˜μ§€ μ•Šμ€ κ²ƒμœΌλ‘œ λ‚˜νƒ€λ‚¬μŠ΅λ‹ˆλ‹€. λ‚΄ 말은 슀크둀 λ§‰λŒ€μ™€ onscroll μ΄λ²€νŠΈκ°€ μ—¬μ „νžˆ μ‹€μ œ μ½˜ν…μΈ  슀크둀과 뢄리될 수 μ—†λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λ‚˜λŠ” λ‹Ήμ‹ μ˜ 아이디어λ₯Ό ν•œ 단계 더 λ°œμ „μ‹œμΌœ μ§„μ •μœΌλ‘œ 연결이 끊긴 μŠ€ν¬λ‘€μ„ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

https://codesandbox.io/embed/absolute-position-scrolling-1u7vj

μ½”λ“œλ₯Ό 보면 Content ꡬ성 μš”μ†Œ μ—μ„œ top 및 left 속성을 제거 ν•˜λ©΄ 슀크둀 λ§‰λŒ€κ°€ ν•  . μ΄λ²ˆμ—λŠ” 마우슀 μ΄λ²€νŠΈκ°€ μ°¨λ‹¨λ˜μ§€ μ•ŠλŠ” 것도 ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€. πŸ˜‚
이제 이 κ΅¬ν˜„μ„ μ‚¬μš©ν•˜μ—¬ onscroll 이벀트λ₯Ό λ¬΄μ‹œν•˜κ³  μ—¬λŸ¬ κ·Έλ¦¬λ“œλ₯Ό μˆ˜λ™μœΌλ‘œ 동기화할 수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. ν•˜μ§€λ§Œ λ¬Όλ‘  더 λ§Žμ€ μž‘μ—…μ΄ ν•„μš”ν•˜λ―€λ‘œ λ‹€μŒ μ‹œκ°„μ„ κΈ°λ‹€λ €μ•Ό ν•©λ‹ˆλ‹€...

이 토둠은 μ €μ—κ²Œ ν˜ΈκΈ°μ‹¬μ„ λΆˆλŸ¬μΌμœΌμΌ°μŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ 두 개의 슀크둀 λ™κΈ°ν™”λœ react-window Grid react-virtualized MultiGrid 와 λΉ„κ΅ν•˜λŠ” ν”„λ‘œμ νŠΈλ₯Ό μ„€μ •ν•˜μ—¬ μ„±λŠ₯이 μ–΄λ–»κ²Œ λΉ„κ΅λ˜λŠ”μ§€ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€. :
https://github.com/bvaughn/react-window-vs-react-virtualized-synced-grids

각각의 μ‚¬μš©λ²•μ„ μ΅œλŒ€ν•œ λΉ„μŠ·ν•˜κ²Œ λ§Œλ“€λ €κ³  λ…Έλ ₯ν–ˆμŠ΅λ‹ˆλ‹€. 일뢀 초기 κ΄€μ°°:

  • react-windowλŠ” DEV λͺ¨λ“œμ—μ„œ λˆˆμ— λ„κ²Œ 느렀 λ³΄μ΄μ§€λ§Œ ν”„λ‘œλ•μ…˜ λΉŒλ“œμ—μ„œλŠ” 쑰금 더 λΉ λ₯΄κ³  λ°˜μ‘μ„±μ΄ μ’‹μŠ΅λ‹ˆλ‹€. (μ—¬κΈ°μ„œ 제 편ν–₯을 λ°°μ œν•˜κΈ° μ–΄λ ΅μŠ΅λ‹ˆλ‹€. μƒμ‚°λŸ‰μ˜ 차이가 더 μž‘μŠ΅λ‹ˆλ‹€.)
  • react-windowλŠ” 슀크둀 μ΄λ²€νŠΈκ°€ λ¨Όμ € ν™œμ„± κ·Έλ¦¬λ“œλ₯Ό μ—…λ°μ΄νŠΈν•œ λ‹€μŒ 계단식 μ—…λ°μ΄νŠΈλ₯Ό 톡해 μˆ˜λ™ κ·Έλ¦¬λ“œλ₯Ό μ—…λ°μ΄νŠΈν•˜κΈ° λ•Œλ¬Έμ— 훨씬 더 λ§Žμ€ 컀밋을 μˆ˜ν–‰ν•©λ‹ˆλ‹€. ν˜„μž¬ onScroll (컀밋 쀑에 ν˜ΈμΆœλ˜λŠ”) λŒ€μ‹  "λ„€μ΄ν‹°λΈŒ"(React) 슀크둀 이벀트 ν•Έλ“€λŸ¬(React의 일괄 μ—…λ°μ΄νŠΈ λ‚΄μ—μ„œ 호좜됨) 전달을 μ§€μ›ν•˜κΈ° μœ„ν•΄ Grid 에 패치λ₯Ό λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€. 단계). 이것은 λ³„λ„μ˜ 계단식 λ Œλ”λ§μ„ λ°©μ§€ν•˜κΈ° λ•Œλ¬Έμ— λ‘œμ»¬μ—μ„œ ν…ŒμŠ€νŠΈν–ˆμ„ λ•Œ 맀우 μœ λ§ν•œ λ³€κ²½ 사항인 것 κ°™μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ κΈ°λ³Έ onScroll 타이밍을 λ³€κ²½ν•˜κ² μŠ΅λ‹ˆλ‹€.

@bvaughn divA -> onScroll -> setState -> ref.scrollTop을 μ‚¬μš©ν•˜μ—¬ κ°€μž₯ 기본적인 바닐라 슀크둀 효과 μ½”λ“œλ₯Ό λ§Œλ“€λ €κ³  μ‹œλ„ν–ˆμ§€λ§Œ μ—¬μ „νžˆ 이 크둬 μŠ€λ ˆλ“œ 슀크둀링 문제λ₯Ό ν•΄κ²°ν•  수 μ—†μ—ˆμŠ΅λ‹ˆλ‹€. λ‚˜λŠ” λΆ„λͺ…νžˆ λ°˜μ‘ μƒνƒœλ₯Ό μš°νšŒν•˜μ§€ μ•Šμ•˜κ³  onScroll ν•Έλ“€λŸ¬ λ‚΄μ—μ„œ ref.scrollTop을 μ„€μ •ν–ˆμ§€λ§Œ κ·Έ μ™Έμ—λŠ” 더 기본적인 방법을 생각할 수 μ—†μŠ΅λ‹ˆλ‹€. κ°€λŠ₯ν•œ ν•œ 적은 수의 λ‹¨κ³„μ—μ„œ μΆ©λΆ„νžˆ λΉ λ₯΄κ²Œ onScroll -> scrollTop을 얻을 수 μ—†λ‹€λ©΄ μ–΄λ–»κ²Œ μˆ˜μ •ν•©λ‹ˆκΉŒ? λ‚΄κ°€ λ­”κ°€λ₯Ό μ™„μ „νžˆ λ†“μΉ˜κ³  μžˆμŠ΅λ‹ˆκΉŒ? 슀크둀(λ˜λŠ” scrollTop μ„€μ •)을 기반으둜 κ·Έλ¦¬λ“œλ₯Ό 이동할 ν•„μš”κ°€ μ—†λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

λͺ©ν‘œλŠ” 항상 JavaScriptκ°€ μŠ€ν¬λ‘€μ„ κ΄€λ¦¬ν•˜λŠ” μŠ€λ ˆλ“œλ₯Ό λ”°λΌκ°ˆ 수 μžˆλ„λ‘ μ΅œλŒ€ν•œ λΉ λ₯΄κ²Œ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

λ‚˜λŠ” λ°˜μ‘ μƒνƒœλ₯Ό μš°νšŒν•˜μ§€ μ•Šμ•˜κ³  onScroll ν•Έλ“€λŸ¬ λ‚΄μ—μ„œ ref.scrollTop을 μ„€μ •ν–ˆμŠ΅λ‹ˆλ‹€.

λͺ…ν™•νžˆν•˜κΈ° μœ„ν•΄ 이것은 λ‚΄ repoλ„ν•˜λŠ” 일이 μ•„λ‹™λ‹ˆλ‹€. λ‚˜λŠ” μ•‘ν‹°λΈŒ κ·Έλ¦¬λ“œμ™€ λ™μΌν•œ (React-wrapped) 이벀트 ν•Έλ“€λŸ¬μ˜ νŒ¨μ‹œλΈŒ κ·Έλ¦¬λ“œμ—μ„œ 슀크둀 μ˜€ν”„μ…‹μ„ μ„€μ •ν•˜κ³  μžˆμœΌλ―€λ‘œ ReactλŠ” μ—…λ°μ΄νŠΈλ₯Ό 단일 λ Œλ”+μ»€λ°‹μœΌλ‘œ 일괄 μ²˜λ¦¬ν•©λ‹ˆλ‹€. 이것은 μ•„λ§ˆλ„ μ†”μ§νžˆ _λ§Žμ€_ 차이λ₯Ό λ§Œλ“€μ§€ μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€.

@ranneyd 와 @bvaughn 이 μ§€κΈˆκΉŒμ§€ κ΄€μ°°ν•œ

  1. λ§Žμ€ κ΅¬ν˜„μ΄ λ°μŠ€ν¬νƒ‘ λΈŒλΌμš°μ €μ—μ„œ μΆ©λΆ„νžˆ 잘 μž‘λ™ν•˜μ§€λ§Œ, 제 μ£Όμš” μ‚¬μš© μ‚¬λ‘€λŠ” μ‹€μ œλ‘œ λͺ¨λ°”일 μž₯μΉ˜μ— 있으며 κ±°κΈ°μ—μ„œ μ—„μ²­λ‚œ μ„±λŠ₯ 차이λ₯Ό λ΄…λ‹ˆλ‹€.

  2. 두 개의 λ‹¨μˆœν•œ 비가상 κ·Έλ¦¬λ“œλ₯Ό λ™κΈ°ν™”ν•˜λŠ” 것은 κ½€ 잘 μž‘λ™ν•©λ‹ˆλ‹€(100% μ™„λ²½ν•˜μ§€λŠ” μ•Šμ§€λ§Œ λͺ¨λ°”μΌμ—μ„œλ„ μΆ©λΆ„νžˆ κ°€κΉμŠ΅λ‹ˆλ‹€). 이것은 λ‚΄ μˆœμ§„ν•˜μ§€λ§Œ μž‘λ™ν•˜λŠ” κ΅¬ν˜„ 이며 μ‹€μ œλ‘œ μž‘λ™ν•˜λŠ” 것을 보기 μœ„ν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μž…λ‹ˆλ‹€ ( yarn storybook ).

  3. "μ œμ–΄λœ" μŠ€ν¬λ‘€μ„ μ‚¬μš©ν•˜λ©΄( 이 μ£Όμ„μ—μ„œ μ œμ•ˆν•œ λŒ€λ‘œ) 두 κ·Έλ¦¬λ“œλ₯Ό 100% 동기화 μƒνƒœλ‘œ μœ μ§€ν•˜μ§€λ§Œ λ°μŠ€ν¬ν†±μ—μ„œλŠ” μƒλ‹Ήνžˆ 느리고 λͺ¨λ°”μΌμ—μ„œλŠ” μ™„μ „νžˆ λ„ˆλ¬΄ λŠλ¦½λ‹ˆλ‹€. 이것은 (맀우 거친 ...) λ‚΄ κ· μ—΄μž…λ‹ˆλ‹€. https://github.com/alonrbar/react-window/commit/c39ce7006dbd590d9c640e37f8a1e78826e4688e

    κ·ΈλŸΌμ—λ„ λΆˆκ΅¬ν•˜κ³  "ν†΅μ œλœ" μ „λž΅ 이 단일 가상 λͺ©λ‘μ—μ„œ

  4. 두 뢄이 이미 μ œμ•ˆν•œ κ²ƒμ²˜λŸΌ _callPropsCallbacks λ₯Ό _onScroll 처리기둜 직접 μ΄λ™ν•˜λ©΄ 동기화 지연을 μ΅œμ†Œν™”ν•˜λŠ” 데 도움이 될 수 μžˆλ‹€κ³  μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€. νŽΈμ§‘ - μ§€κΈˆ μ‹œλ„ν–ˆμ§€λ§Œ μ‹€μ œλ‘œ λ„μ›€μ΄λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€ 😞

  5. μ–΄λ–€ μ‹μœΌλ‘œλ“  IMHOλŠ” ꡬ성 μš”μ†Œμ˜ λ‚˜λ¨Έμ§€ λΆ€λΆ„(후크일 μˆ˜λ„ 있음)μ—μ„œ 가상화 논리λ₯Ό λΆ„λ¦¬ν•˜μ—¬ λ Œλ”λ§ 및 온슀크둀 ν•­λͺ©μ„ λ³„λ„λ‘œ μ²˜λ¦¬ν•˜κ³  μ‰½κ²Œ λΉ„κ΅ν•˜κ³  λŸ°νƒ€μž„μ— μ „ν™˜ν•  수 μžˆλ„λ‘ ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. ꡬ성 μ†Œν’ˆ. λ˜ν•œ 이 논리λ₯Ό 내보내고 μ‚¬μš©μžκ°€ λ™μΌν•œ 논리λ₯Ό 기반으둜 μ‚¬μš©μž 지정 ꡬ성 μš”μ†Œ(예: 이 μ£Όμ„μ˜ @ranneyd μ†”λ£¨μ…˜)λ₯Ό κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

생각?

@alonrbar μ ˆλŒ€ μœ„μΉ˜ 지정을 μˆ˜ν–‰ν•˜λŠ” λ‚΄ μ†”λ£¨μ…˜μ€ μŠ€ν¬λ‘€μ„ μˆ˜ν–‰ν•˜λŠ” κ·Έλ¦¬λ“œκ°€ μ—†μœΌλ―€λ‘œ μ•½ 300x300κΉŒμ§€ 맀우 잘 μž‘λ™ν•©λ‹ˆλ‹€. μ•½κ°„ μ§€μ—°λ©λ‹ˆλ‹€). 더 큰 ν¬κΈ°μ—μ„œλŠ” 큰 배열에 λŒ€ν•œ 처리/맀핑이라고 μƒκ°ν•©λ‹ˆλ‹€. λͺ‡ 가지 μ΅œμ ν™”κ°€ μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.
ν•˜μ§€λ§Œ ν•  μˆ˜λŠ” μžˆμŠ΅λ‹ˆλ‹€. 제 μƒλ‹Ήνžˆ κ°„λ‹¨ν•œ 가상화 κ΅¬ν˜„λ§ŒνΌ 슀크둀 동기화와 관련이 μžˆλ‹€κ³  μ™„μ „νžˆ ν™•μ‹ ν•  μˆ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ 더 λ§Žμ€ 캐싱을 μˆ˜ν–‰ν•  수 있고 λ Œλ”λ§ κΈ°λŠ₯을 μ „ν˜€ ν˜ΈμΆœν•˜μ§€ μ•ŠκΈ° μœ„ν•΄ 셀을 더 일찍 가상화해야 ν•˜λŠ”μ§€ μ—¬λΆ€λ₯Ό 계산할 수 μžˆμŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” λͺ¨λ°”μΌμ—μ„œ 아무것도 ν…ŒμŠ€νŠΈν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. μž μ‹œ 후에 μ‹œλ„ν•΄ λ³Ό 수 μžˆλŠ” λͺ‡ 가지 μ½”λ“œλ₯Ό μ œκ³΅ν•˜κ² μŠ΅λ‹ˆλ‹€.

@bvaughn ν…ŒμŠ€νŠΈλ₯Ό 정말 보고 μ‹ΆμŠ΅λ‹ˆλ‹€. κ·ΈλŠ” λ„€μ΄ν‹°λΈŒ μŠ€ν¬λ‘€μ— 직접 μ—°κ²°ν•˜λ©΄ λ¬Έμ œκ°€ ν•΄κ²°λ˜μ§€λ§Œ 당신은 그렇지 μ•Šλ‹€κ³  λ§ν•©λ‹ˆλ‹€. 직접 보고 μ‹ΆμŠ΅λ‹ˆλ‹€.

가상화 논리λ₯Ό 후크 λ˜λŠ” 독립 κΈ°λŠ₯으둜 λŒμ–΄μ˜€λŠ” ν•œ, 논리가 본질적으둜 뷰에 μ—°κ²°λ˜μ–΄ 있기 λ•Œλ¬Έμ— μƒλ‹Ήνžˆ κΉŒλ‹€λ‘œμ›Œμ§‘λ‹ˆλ‹€. λ˜ν•œ λ§Žμ€ μ„±λŠ₯ μ‘°μ •μ—λŠ” ν•˜λ‚˜μ˜ 후크 λ˜λŠ” κΈ°λŠ₯으둜 μΊ‘μŠν™”ν•˜κΈ° μ–΄λ €μšΈ 수 μžˆλŠ” 캐싱 및 λ©”λͺ¨μ΄μ œμ΄μ…˜ ν•­λͺ©μ΄ ν¬ν•¨λ˜κ±°λ‚˜ μ΅œμ†Œν•œ λ™μΌν•œ μ„±λŠ₯을 얻을 수 μžˆλŠ” 정도인 것 κ°™μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ‚˜λŠ” λ‚΄κ°€ 가진 것을 보고 μ–Όλ§ˆλ‚˜ λ§Žμ€ 논리λ₯Ό λŒμ–΄λ‚Ό 수 μžˆλŠ”μ§€ λ³Ό κ²ƒμž…λ‹ˆλ‹€.

μΆ”μ‹ :
μ•„λ§ˆ μž‘λ™ν•˜μ§€ μ•Šμ„ 것이라고 방금 μƒκ°ν•œ ν•œ κ°€μ§€λŠ” denounce와 같은 것 + CSS μ „ν™˜μ„ μˆ˜ν–‰ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 100msλ§ˆλ‹€ ν•˜λ‚˜μ˜ 슀크둀 이벀트만 μ‹€ν–‰ν•˜κ³  μ›€μ§μž„μ„ μ• λ‹ˆλ©”μ΄μ…˜ν•˜λ©΄ 더 μ’‹μ•„ 보일 수 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ μƒλ‹Ήνžˆ 덜 λ°˜μ‘μ μœΌλ‘œ 보일 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μ›”λ“œ 였브 μ›Œν¬λž˜ν”„νŠΈμ™€ λΉ„μŠ·ν•©λ‹ˆλ‹€(지연 λ˜λŠ” κΈ΄ λŒ€κΈ° μ‹œκ°„μ΄ μžˆλŠ” 경우 캐릭터λ₯Ό μ§μ„ μœΌλ‘œ μ΄λ™ν•œ λ‹€μŒ μ‹€μ œλ‘œ μ΄λ™ν•œ μœ„μΉ˜μ— λŒ€ν•œ 정보λ₯Ό 얻은 ν›„ μˆ˜μ •ν•©λ‹ˆλ‹€).

@bvaughn ν…ŒμŠ€νŠΈλ₯Ό 정말 보고 μ‹ΆμŠ΅λ‹ˆλ‹€. κ·ΈλŠ” λ„€μ΄ν‹°λΈŒ μŠ€ν¬λ‘€μ— 직접 μ—°κ²°ν•˜λ©΄ λ¬Έμ œκ°€ ν•΄κ²°λ˜μ§€λ§Œ 당신은 그렇지 μ•Šλ‹€κ³  λ§ν•©λ‹ˆλ‹€. 직접 보고 μ‹ΆμŠ΅λ‹ˆλ‹€.

μ €λŠ” κ·Έλ ‡κ²Œ λ§ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€ :smile: 단지 λΆˆν•„μš”ν•œ λ Œλ”λ§κ³Ό DOM λ³€ν˜•μ„ λ°©μ§€ν•œλ‹€κ³  λ§ν–ˆμŠ΅λ‹ˆλ‹€. μ‹€μ œ μ„±λŠ₯에 λ―ΈμΉ˜λŠ” 영ν–₯이 μ–΄λŠ 정도인지 λ‚˜μ—κ²ŒλŠ” λΆˆλΆ„λͺ…ν•©λ‹ˆλ‹€. κ·ΈλŸΌμ—λ„ λΆˆκ΅¬ν•˜κ³  μ „λ°˜μ μœΌλ‘œ 긍정적인 변화인 것 κ°™μŠ΅λ‹ˆλ‹€.

@alonrbar @bvaughn μ‹€μ œλ‘œ λ‚΄ μ½”λ“œλ₯Ό λ¬Έμ„œν™”ν•΄μ•Ό ν•˜μ§€λ§Œ 여기에 μ΅œμ‹  버전이 μžˆμŠ΅λ‹ˆλ‹€.

https://github.com/ranneyd/synced-table

@alonrbar @bvaughn κ·Έλž˜μ„œ μ—¬κΈ° λ‚΄κ°€ 방금 λ°œκ²¬ν•œ μž¬λ―ΈμžˆλŠ” 것이 μžˆμŠ΅λ‹ˆλ‹€:

λ‚΄ μ†”λ£¨μ…˜μ€ macbook ν™”λ©΄μ˜ Chrome 75μ—μ„œ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ™λ£Œκ°€ 크둬을 μ—…λ°μ΄νŠΈν•˜μ§€ μ•Šμ•˜μ„ λ•Œ μž‘λ™ν–ˆμŠ΅λ‹ˆλ‹€. μ™ΈλΆ€ λͺ¨λ‹ˆν„°λ₯Ό μ‚¬μš©ν•˜λ©΄ μž‘λ™ν•©λ‹ˆλ‹€. λ…ΈνŠΈλΆ ν™”λ©΄μ—μ„œλŠ” μ§€μ—°λ©λ‹ˆλ‹€.
😩

흠... μ™ΈλΆ€ λͺ¨λ‹ˆν„°μ™€ μž¬μƒλ₯ μ΄λ‚˜ λ°°μœ¨μ— μ•½κ°„μ˜ 차이가 μžˆμŠ΅λ‹ˆλ‹€. "μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€"라고 λ§ν•˜λ©΄ ꡬ체적으둜 무엇을 μ˜λ―Έν•©λ‹ˆκΉŒ?

λ‚΄ 잘λͺ»μ΄μ•Ό. 슀크둀이 더 이상 λ™κΈ°ν™”λ˜μ§€ μ•ŠμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€. λ‚΄ repoλ₯Ό λ³΅μ œν•˜μ—¬ μ‹€ν–‰ν•˜λ©΄ μ™ΈλΆ€ λͺ¨λ‹ˆν„°μ™€ λ…ΈνŠΈλΆ 화면을 비ꡐ할 수 μžˆμŠ΅λ‹ˆλ‹€. λͺ¨λ‹ˆν„°μ—μ„œ 그듀은 μ™„λ²½ν•˜κ²Œ λ™κΈ°ν™”λ©λ‹ˆλ‹€. λž©ν†± ν™”λ©΄μ—μ„œ 헀더가 κΉœλ°•μž…λ‹ˆλ‹€(슀크둀링 μš”μ†Œμ™€ λ™μΌν•œ μ†λ„λ‘œ μ—…λ°μ΄νŠΈν•˜μ§€ μ•ŠμŒ).

λ‚˜λŠ” μ‹€μ œλ‘œ ν¬κΈ°ν–ˆκ³  position: sticky μ‹œλ„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. 그것은 μ‹€μ œλ‘œ μž‘λ™ν•©λ‹ˆλ‹€. λΈŒλΌμš°μ € 지원이 100%λŠ” μ•„λ‹ˆμ§€λ§Œ μ‹€μ œλ‘œλŠ” 1λ…„ 전보닀 훨씬 λ‚˜μ•„μ‘ŒμŠ΅λ‹ˆλ‹€.

μž‘λ™ν•  수 μžˆλŠ” 폴리필이 μ•„λ‹Œ 폴리필인 이 λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μžˆμ§€λ§Œ μš°λ¦¬κ°€ λͺ©ν‘œλ‘œ ν•˜λŠ” λΈŒλΌμš°μ €λŠ” μš°μ—°νžˆ 이 κΈ°λŠ₯을 μ§€μ›ν•©λ‹ˆλ‹€.
https://github.com/dollarshaveclub/stickybits

@alonrbar @bvaughn 이 μ΅œμ‹  λ²„μ „μž…λ‹ˆλ‹€. position: sticky ν•©λ‹ˆλ‹€. readmeμ—μ„œ 쑰금 μ„€λͺ…ν•˜κ² μŠ΅λ‹ˆλ‹€. μ½”λ“œλŠ” μ—¬μ „νžˆ λ¬Έμ„œν™”ν•΄μ•Ό ν•©λ‹ˆλ‹€.

https://github.com/ranneyd/sticky-table

λ‚΄ μ†”λ£¨μ…˜μ€ macbook ν™”λ©΄μ˜ Chrome 75μ—μ„œ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ™λ£Œκ°€ 크둬을 μ—…λ°μ΄νŠΈν•˜μ§€ μ•Šμ•˜μ„ λ•Œ μž‘λ™ν–ˆμŠ΅λ‹ˆλ‹€. μ™ΈλΆ€ λͺ¨λ‹ˆν„°λ₯Ό μ‚¬μš©ν•˜λ©΄ μž‘λ™ν•©λ‹ˆλ‹€. λ…ΈνŠΈλΆ ν™”λ©΄μ—μ„œλŠ” μ§€μ—°λ©λ‹ˆλ‹€.
😩

@ranneyd 였늘

@bvaughn κ·Έλž˜μ•Ό ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. OSλŠ” 60hzλ₯Ό 보내고 μžˆλ‹€κ³  λ§ν•˜κ³  λͺ¨λ‹ˆν„° 사양은 60hz라고 μƒκ°ν•˜μ§€λ§Œ λˆ„κ΅°κ°€κ°€ 거짓말을 해도 놀라지 μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€ πŸ˜‚

@ranneyd μ§€κΈˆμ€ useVirtual 후크 및 λ Œλ”λ§μ—μ„œ λ‘œμ§μ„ μš°μ•„ν•˜κ²Œ λΆ„λ¦¬ν•©λ‹ˆλ‹€.
react-window λŒ€ν•œ pull μš”μ²­μ„ μ–΄λ–»κ²Œλ“  μƒμ„±ν•˜κ³  κ±°κΈ°μ—μ„œ μ‚¬μš©ν•˜κ³  λ Œλ” λ‘œμ§μ„ μ—°κ²°ν•  수 μžˆλŠ” μΌμ’…μ˜ renderTable λ©”μ„œλ“œλ₯Ό λ…ΈμΆœν•  수 μžˆλ‹€λ©΄ 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œν•˜λ©΄ λΌμ΄λΈŒλŸ¬λ¦¬κ°€ λ°˜μ‘ 창을 κ΅μ²΄ν•˜λŠ” λŒ€μ‹  λž˜ν•‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ‚˜λŠ” μš°λ¦¬κ°€ 이 μ ‘κ·Ό 방식을 ν™œμš©ν•˜κ³  이미 λ§Žμ€ ν…ŒμŠ€νŠΈλ₯Ό κ±°μ³€κ³  널리 퍼진 react-window λ‚΄λΆ€μ˜ 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλ‹€λ©΄ μ„ ν˜Έν•  것이라고 λ―ΏμŠ΅λ‹ˆλ‹€.

λ‹€λ₯Έ 문제둜, scrollTo κ°€ 직접 DOM μ‘°μž‘μ„ μ‚¬μš©ν•œλ‹€λ©΄(μƒνƒœλ₯Ό μ„€μ •ν•˜λŠ” 것 외에 μ–΄λ–€ κ²½μš°λ“  κ·Έλ ‡κ²Œ ν•˜κΈ° 전에) 두 ν…Œμ΄λΈ”μ„ λ™κΈ°ν™”ν•˜λŠ” κ²°κ³Όκ°€ 더 λΆ€λ“œλŸ¬μ›Œμ§ˆ 것이라고 μƒκ°ν•©λ‹ˆλ‹€. λ‚΄κ°€ μ°©κ°ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ @bvaughn 은 λ˜ν•œμ΄ λ°©ν–₯으둜 무언가λ₯Ό μ œμ•ˆν•˜κ³ μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

@ranneyd κ·€ν•˜μ˜ κ³ μ • ν…Œμ΄λΈ” μ†”λ£¨μ…˜μ€ 정말 ν›Œλ₯­ν•΄ 보이며 μ‚¬μš©ν•  수 있게 λ˜μ–΄ 맀우 κΈ°μ©λ‹ˆλ‹€. npm 에 μ‚¬μš©ν•  수 μžˆλŠ” APIλ₯Ό μΆœμ‹œν•˜λŠ” 것을 κ³ λ €ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?

@bvaughn @ranneyd

κ·Έλž˜μ„œ κ½€ 였랜 μ‹œκ°„μ΄ μ§€λ‚œ ν›„ λ‚˜λŠ” μ΅œκ·Όμ— 이 문제둜 λŒμ•„μ™”μŠ΅λ‹ˆλ‹€. λΌμ΄λΈŒλŸ¬λ¦¬μ™€ Recyclerlistview 및 react-virtual-grid의 μ½”λ“œμ™€ 아이디어λ₯Ό μ‚¬μš©ν•˜μ—¬ λ§ˆμΉ¨λ‚΄ μ›ν•˜λŠ” λ™μž‘, 즉 λ°μŠ€ν¬ν†±κ³Ό λͺ¨λ°”일 λͺ¨λ‘μ—μ„œ 잘 μž‘λ™ν•˜λŠ” κ³ μ •λœ ν–‰κ³Ό 열이 μžˆλŠ” κ³ μ„±λŠ₯ κ·Έλ¦¬λ“œλ₯Ό 달성할 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. μž₯치(빈/백색 μ…€ 없이 λΆ€λ“œλŸ¬μš΄ 슀크둀).

κ·Έκ²ƒμ˜ TLDR은 λ‚΄κ°€ λˆμ ν•œ μœ„μΉ˜ 지정과 ν•¨κ»˜ μž¬ν™œμš©μ„ μ‚¬μš©ν•œλ‹€λŠ” 것이고 κ°€μž₯ ν₯미둜운 μ½”λ“œλŠ” 이 방법 μ—μ„œ 찾을 수 μžˆλ‹€λŠ”

또 λ‹€λ₯Έ μ†”λ£¨μ…˜μ„ μž‘μ„±ν•˜κ²Œ 된 동기에 λŒ€ν•œ ν¬λ ˆλ”§ 등이 여기에 μžˆμŠ΅λ‹ˆλ‹€ . 감사 ν•΄μš”!

λ‚˜μ€‘μ— λ‹€λ₯Έ μ‚¬λžŒμ΄ 이 문제λ₯Ό λ°œκ²¬ν•  경우λ₯Ό λŒ€λΉ„ν•˜μ—¬ μž‘μ—… 쀑인 Code Sandbox μ˜ˆμ œμ— λŒ€ν•œ 링크λ₯Ό 여기에 남길 κ²ƒμž…λ‹ˆλ‹€.
https://codesandbox.io/s/y3pyp85zm1

μ•„μ£Ό μ’‹μŠ΅λ‹ˆλ‹€. μ™„μ „νžˆ 였λ₯Έμͺ½μœΌλ‘œ μŠ€ν¬λ‘€ν•  λ•ŒκΉŒμ§€: 그러면 헀더가 λ‚΄μš©κ³Ό 잘λͺ» μ •λ ¬λ©λ‹ˆλ‹€(슀크둀 수직 슀크둀 λ§‰λŒ€μ˜ λ„ˆλΉ„λ§ŒνΌ).
ν˜Ήμ‹œλΌλ„ κ·Έ 해결책을 μ°Ύμ•˜κ² μŠ΅λ‹ˆκΉŒ?
감사 ν•΄μš”

λ‚˜μ€‘μ— λ‹€λ₯Έ μ‚¬λžŒμ΄ 이 문제λ₯Ό λ°œκ²¬ν•  경우λ₯Ό λŒ€λΉ„ν•˜μ—¬ μž‘μ—… 쀑인 Code Sandbox μ˜ˆμ œμ— λŒ€ν•œ 링크λ₯Ό 여기에 남길 κ²ƒμž…λ‹ˆλ‹€.
https://codesandbox.io/s/y3pyp85zm1

μ•„μ£Ό μ’‹μŠ΅λ‹ˆλ‹€. μ™„μ „νžˆ 였λ₯Έμͺ½μœΌλ‘œ μŠ€ν¬λ‘€ν•  λ•ŒκΉŒμ§€: 그러면 헀더가 λ‚΄μš©κ³Ό 잘λͺ» μ •λ ¬λ©λ‹ˆλ‹€(슀크둀 수직 슀크둀 λ§‰λŒ€μ˜ λ„ˆλΉ„λ§ŒνΌ).
ν˜Ήμ‹œλΌλ„ κ·Έ 해결책을 μ°Ύμ•˜κ² μŠ΅λ‹ˆκΉŒ?
감사 ν•΄μš”

전체 곡개: λ‚˜λŠ” μ‹€μ œλ‘œ μ²˜μŒλΆ€ν„° λ‚΄ μžμ‹ μ˜ 버전을 λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€. 이 라이브러리λ₯Ό 기반으둜 ν•˜λŠ” 자체 가상화가 μžˆμŠ΅λ‹ˆλ‹€. λ‚΄κ°€ μ΄λ ‡κ²Œ ν•œ μ΄μœ λŠ” MacBookκ³Ό νŠΉμ • Chrome ν”Œλž˜κ·Έμ—μ„œ 슀크둀 μ• λ‹ˆλ©”μ΄μ…˜μ΄ JS와 λ‹€λ₯Έ νƒ€μ΄λ°μœΌλ‘œ λ°œμƒν•˜λŠ” λ¬Έμ œκ°€ 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€. ScrollSyncλ₯Ό μ‚¬μš©ν•˜λ €λ©΄ λ„ˆλ¬΄ λ§Žμ€ 전달 ν•¨μˆ˜ 호좜이 ν•„μš”ν•˜κ³  λ„ˆλ¬΄ λŠλ ΈμŠ΅λ‹ˆλ‹€. 기본적으둜 핡심에 κ³ μ • 헀더가 μžˆλŠ” 라이브러리λ₯Ό λ‹€μ‹œ λ§Œλ“€μ–΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€(이 μŠ€λ ˆλ“œμ˜ μ•žλΆ€λΆ„μ—μ„œ λ§ν–ˆλ“―μ΄ position: sticky μ‚¬μš©ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. μ–Έμ  κ°€λŠ” μ§€κΈˆ 가지고 μžˆλŠ” 것을 μ—…λ‘œλ“œν•΄μ•Ό ν•©λ‹ˆλ‹€).

즉, 이 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 방법은 overflow: scroll λ₯Ό μ‚¬μš©ν•˜μ—¬ 슀크둀 λ§‰λŒ€λ₯Ό κ°•μ œ μ‹€ν–‰ν•œ λ‹€μŒ ν•΄λ‹Ή νŒ¨λ”©μ„ λ§ˆμ§€λ§‰ 셀에 μΆ”κ°€ν•˜κ±°λ‚˜ ref 내뢀에 보이지 μ•ŠλŠ” divλ₯Ό λ„£κ³  슀크둀 λ§‰λŒ€ 크기λ₯Ό μΈ‘μ •ν•˜κ³  DOM λ…Έλ“œλ₯Ό μ‚­μ œν•©λ‹ˆλ‹€.

μŠ€ν¬λ‘€λ°” μ˜€λ²„λ ˆμ΄λ₯Ό λ§Œλ“œλŠ” overflow-y: overlay λ₯Ό μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€. λΆˆν–‰νžˆλ„ μ›Ήν‚· λΈŒλΌμš°μ €μ—μ„œλ§Œ μž‘λ™ν•©λ‹ˆλ‹€.

μ•Œκ² μŠ΅λ‹ˆλ‹€. 정보 κ°μ‚¬ν•©λ‹ˆλ‹€. μŠ€ν‹°ν‚€ ν—€λ”λŠ” 맀우 일반적인 μš”κ΅¬ μ‚¬ν•­μ΄λ―€λ‘œ react-window에 μŠ€ν‹°ν‚€ν•œ 첫 번째 ν–‰ μ˜΅μ…˜μ„ μΆ”κ°€ν•˜λŠ” κ²ƒλ§ŒμœΌλ‘œλ„ 더 λ§Žμ€ κ²½μš°μ— λ°˜μ‘ 가상화λ₯Ό λŒ€μ²΄ν•˜κ²Œ 될 κ²ƒμž…λ‹ˆλ‹€. κ·Έλ ‡κ²Œ μƒκ°ν•˜μ§€ μ•Šμ•„?

@ranneyd λ‹€μ‹œ ν•œ 번 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€. κ·€ν•˜μ˜ μ ‘κ·Ό 방식을 λ”°λžκ³  슀크둀 동기화가

μŠ€ν¬λ‘€λ°”μ˜ μˆ¨κ²¨μ§„ μ˜€λ²„ν”Œλ‘œλŠ” κ·Έλ¦¬λ“œ 끝 κ·Όμ²˜μ—μ„œ μ •λ ¬ λΆˆλŸ‰μ„ μΌμœΌν‚΅λ‹ˆλ‹€.

gridalignement

이 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 방법에 λŒ€ν•œ μ œμ•ˆ 사항이 μžˆμŠ΅λ‹ˆκΉŒ?

μ½”λ“œμƒŒλ“œλ°•μŠ€ 예

미리 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€

νŒŒν‹°μ— λŠ¦μ—ˆμ§€λ§Œ leftRef에 ν•œ 행을 μΆ”κ°€ν•˜κ³  μ˜€λ²„ν”Œλ‘œλ₯Ό μˆ¨κΉ€μœΌλ‘œ μ„€μ •ν•˜λ©΄ 기본적으둜 pbλ₯Ό ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€. (leftRef -> main Gridλ₯Ό λ™κΈ°ν™”ν•˜μ§€ μ•Šμ•„λ„ λ˜λ„λ‘ ν–ˆμŠ΅λ‹ˆλ‹€.

  const headerRef = React.useRef();
  const leftRef   = React.useRef();

  return <Box classes={{
            root:classes.tableContainer
          }}>
      <AutoSizer>
        {({ height, width }) => (<>
        {/*---------------- LAΒ TABLE -------------*/}
          <Grid
            columnCount={1000}
            columnWidth={100}
            height={height}
            rowCount={1000}
            rowHeight={35}
            width={width}
            onScroll={({ scrollLeft, scrollTop }) => {
              if (leftRef.current) {
                leftRef.current.scrollTo({ scrollTop });
              }
              if (headerRef.current) {
                headerRef.current.scrollTo({ scrollLeft });
              }
            }}
          >
            {({ columnIndex, rowIndex, style }) => (
              <Box style={style} classes={{root:classes.cell}}>
                Item {rowIndex},{columnIndex}
              </Box>
            )}
          </Grid>
          {/*---------------- HEADER -------------*/}
          <Grid
            ref={headerRef}
            outerElementType={React.forwardRef((props, ref) => (
              <div ref={ref}  {...props} style={{...props.style,position:"absolute",overflow:"hidden",top:0,right:0,left:150}} />
            ))}
            columnCount={1001}  /*columns count +1 for scroll problems*/
            columnWidth={100}
            height={60}
            rowCount={1}
            rowHeight={60}
            width={width}
          >
            {({ columnIndex, rowIndex, style }) => (
              <Box style={style} classes={{root:classes.headerCell}}>
                Header {rowIndex},{columnIndex}
              </Box>
            )}
          </Grid>  
          {/*---------------- LEFTΒ COL -------------*/}
          <Grid
            ref={leftRef}
            outerElementType={React.forwardRef((props, ref) => (
              <div ref={ref}  {...props} style={{...props.style,position:"absolute",overflow:"hidden",top:60,left:0}} />
            ))}
            columnCount={1}
            columnWidth={150}
            height={height}
            rowCount={251} /** add 1 for scroll problems at the end */
            rowHeight={140}
            width={150}
          >
            {({ columnIndex, rowIndex, style }) => (
              <Box style={style} classes={{root:classes.headerCell}}>
                Left {rowIndex},{columnIndex}
              </Box>
            )}
          </Grid>  
        </>)}
      </AutoSizer>
    </Box>
이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰