React-window: استخدام عنصر جدول html

تم إنشاؤها على ٢١ سبتمبر ٢٠١٨  ·  34تعليقات  ·  مصدر: bvaughn/react-window

هل لديك مثال على استخدام هذا مع الجداول؟ أحاول أن أجعلها تعمل ولكن لدي شك قوي في أنها إما لا تعمل ، أو أنني أفعل شيئًا خاطئًا للغاية.
لقد قمت بتعيين اسم OuterTagName إلى "جدول" و innerTagName على "tbody" ، لكن لا يمكنني التمرير.

هذا هو الكود الخاص بي ، لست متأكدًا مما إذا كان مفيدًا (العناصر عبارة عن قائمة بالكائنات):

 <List
            outerRef={this._list}
            outerTagName="table"
            innerTagName="tbody"
            height={300}
            itemData={items}
            itemSize={() => 30}
            itemCount={items.length}
            itemKey={item => item.uniqueId}>
            {({index, style, data}) => {
              return (
                <tr style={style} key={index}>
                  <td>Item {index}</td>
                </tr>
              );
            }}
          </List>
💬 question

التعليق الأكثر فائدة

pupudu أشيد أقرر محاولة معالجة هذا بمفردي. أردت فقط الشيء الفائق الوضوح الذي كان يبحث عنه الآخرون: هذه المكتبة ولكن مع عناصر الجدول.

تبين أنني تمكنت من تنفيذ هذا باستخدام القليل جدًا من التعليمات البرمجية ، والكثير من الإبداع. الكود بسيط بما يكفي بحيث يمكن لأي شخص نسخ / لصق وتوسيع حسب رغبته. bvaughn بعد معرفة الكيفية ، سيكون هذا تافهًا جدًا لإضافته إلى المكتبة إذا كنت تريد ، ولكن أيضًا تافهًا جدًا لتجاوزه إذا كنت تعرف كيف.

باختصار :

  • التقط النمط "العلوي" للصف الأول بعد العرض
  • قم بتخزين هذه القيمة في React.Context حتى نتمكن من تمريرها
  • قم بتطبيق القيمة على مكون جدول والذي سيكون هو ما يتم نقله ، بدلاً من الصفوف نفسها
  • أضف فتحات إضافية لأشياء مثل الرؤوس والتذييلات.
  • لا تسمح بيئة العمل في المكتبة بتمرير الأشياء بدقة ، لذا فإن React.Context هو البطل للتغلب على الاتصال عبر المكونات.

وضع حماية كود العمل: https://codesandbox.io/s/react-window-with-table-elements-d861o

رمز كمرجع

import React from 'react'
import { useState, useRef, useContext } from 'react'
import { FixedSizeList, FixedSizeListProps } from 'react-window'
import { render } from 'react-dom'

/** Context for cross component communication */
const VirtualTableContext = React.createContext<{
  top: number
  setTop: (top: number) => void
  header: React.ReactNode
  footer: React.ReactNode
}>({
  top: 0,
  setTop: (value: number) => {},
  header: <></>,
  footer: <></>,
})

/** The virtual table. It basically accepts all of the same params as the original FixedSizeList.*/
function VirtualTable({
  row,
  header,
  footer,
  ...rest
}: {
  header?: React.ReactNode
  footer?: React.ReactNode
  row: FixedSizeListProps['children']
} & Omit<FixedSizeListProps, 'children' | 'innerElementType'>) {
  const listRef = useRef<FixedSizeList | null>()
  const [top, setTop] = useState(0)

  return (
    <VirtualTableContext.Provider value={{ top, setTop, header, footer }}>
      <FixedSizeList
        {...rest}
        innerElementType={Inner}
        onItemsRendered={props => {
          const style =
            listRef.current &&
            // @ts-ignore private method access
            listRef.current._getItemStyle(props.overscanStartIndex)
          setTop((style && style.top) || 0)

          // Call the original callback
          rest.onItemsRendered && rest.onItemsRendered(props)
        }}
        ref={el => (listRef.current = el)}
      >
        {row}
      </FixedSizeList>
    </VirtualTableContext.Provider>
  )
}

/** The Row component. This should be a table row, and noted that we don't use the style that regular `react-window` examples pass in.*/
function Row({ index }: { index: number }) {
  return (
    <tr>
      {/** Make sure your table rows are the same height as what you passed into the list... */}
      <td style={{ height: '36px' }}>Row {index}</td>
      <td>Col 2</td>
      <td>Col 3</td>
      <td>Col 4</td>
    </tr>
  )
}

/**
 * The Inner component of the virtual list. This is the "Magic".
 * Capture what would have been the top elements position and apply it to the table.
 * Other than that, render an optional header and footer.
 **/
const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
  function Inner({ children, ...rest }, ref) {
    const { header, footer, top } = useContext(VirtualTableContext)
    return (
      <div {...rest} ref={ref}>
        <table style={{ top, position: 'absolute', width: '100%' }}>
          {header}
          <tbody>{children}</tbody>
          {footer}
        </table>
      </div>
    )
  }
)

/**
 * Render Our Example
 **/
render(
  <VirtualTable
    height={300}
    width="100%"
    itemCount={1000}
    itemSize={36}
    header={
      <thead>
        <tr>
          <th>Index</th>
          <th>Header 2</th>
          <th>Header 3</th>
          <th>Header 4</th>
        </tr>
      </thead>
    }
    row={Row}
    footer={
      <tfoot>
        <tr>
          <td>Footer 1</td>
          <td>Footer 2</td>
          <td>Footer 3</td>
          <td>Footer 4</td>
        </tr>
      </tfoot>
    }
  />,
  document.querySelector('main')
)

ال 34 كومينتر

لا أعتقد أن هذا سينجح حقًا. على حد علمي ، لا يدعم HTMLTableElement حقًا التدفق الزائد بالطريقة التي يحتاجها مكون النوافذ. يمكنك _could_ تغيير النمط إلى display: block لكن ما زلت لا أعتقد أنه سيعمل بشكل صحيح. ( هذا مثال .)

لماذا تحتاج طاولة؟ أعتقد أنه يمكنك تحقيق نفس تخطيط العمود باستخدام كتل مضمنة أو تخطيطات مرنة.

زوجان من الأشياء الإضافية:

  • أنت لا تحدد معلمة طلب width إلى List
  • لست بحاجة إلى إضافة key إلى صفوفك
  • يمكن أن يكون itemSize مجرد 30 بدلاً من () => 30 (سيكون أداؤه أفضل قليلاً)

شكرا على الرد السريع.
لقد ناقشنا بالفعل إعادة كتابته إلى divs ، ولكن نظرًا لأن هذا لمكون موجود كبير إلى حد ما ، أردنا فقط التأكد قبل البدء في إعادة الكتابة. رأيت بعض التعليقات الأخرى حول طاولة التحكم عن بعد ، لذا فكرت أنه ربما كان من المفترض أن يعمل.
على أي حال ، لا تمانع في إعادة الكتابة ، أعتقد أن الأمر يستحق ذلك.

تلقيت تحذيرات من React بشأن المفاتيح بدون المفتاح الموجود في الصف ، الأمر الذي كان محيرًا بالنسبة لي أيضًا بالنظر إلى أنني أضع مفتاح عنصر ، لذا لست متأكدًا مما يحدث هناك.

شكرا

اينار

في 21 سبتمبر 2018 ، الساعة 16:52 ، كتب Brian Vaughn [email protected] :

لا أعتقد أن هذا سينجح حقًا. على حد علمي ، لا تدعم HTMLTableElement حقًا تجاوز السعة بالطريقة التي يحتاجها مكون النوافذ. يمكنك تغيير النمط للعرض: حظر ولكني ما زلت لا أعتقد أنه سيعمل بشكل صحيح.

لماذا تحتاج طاولة؟ أعتقد أنه يمكنك تحقيق نفس تخطيط العمود باستخدام كتل مضمنة أو تخطيطات مرنة.

زوجان من الأشياء الإضافية:

أنت لا تحدد عرض معلمة طلب للقائمة
لست بحاجة إلى إضافة المفتاح إلى صفوفك
يمكن أن يكون itemSize 30 فقط بدلاً من () => 30 (سيكون أداؤه أفضل قليلاً)
-
أنت تتلقى هذا لأنك قمت بتأليف الموضوع.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو اعرضها على GitHub ، أو قم بكتم صوت الموضوع.

تلقيت تحذيرات من React بشأن المفاتيح بدون المفتاح الموجود في الصف ، الأمر الذي كان محيرًا بالنسبة لي أيضًا بالنظر إلى أنني أضع مفتاح عنصر ، لذا لست متأكدًا مما يحدث هناك.

هذا غير متوقع. هل يمكنك مشاركة حالة إعادة برو معي (عبر Code Sandbox)؟

أوه آسف. يجب أن أضيف أن هذا سيكون متوقعًا _ فقط_ إذا أعادت الدالة itemKey undefined لبعض العناصر - وفي هذه الحالة يجب أن يكون الإصلاح لهذه الوظيفة.

bvaughn لا أجد أي شيء محدد حول دعم تجاوز السعة باعتباره عاملاً مقيدًا. من الغريب ، أود أن أعرف ماذا يمكن أن يكون. أنا بالتأكيد أتفهم أن دعم الوظائف الأساسية لكليهما قد يكون مملاً ، لكنه يبدو فقط أن عنصر القائمة الأساسي هو كل ما هو خارج اختيار المنفذ في الوقت الحالي. بالحديث عن نفسي وعن أي شخص قد يستخدم نافذة رد الفعل مع سيناريوهات رأس ثابتة ، سيكون من الجيد الحصول على الدعم الجدولي المتأصل المضمن في تخطيطات الجدول. استخدام العرض: يأخذ الجدول "بعضًا" من عبء التطوير وهو تخطيط لمرة واحدة للتطبيقات المحيطة التي قد يتم إنشاؤها باستخدام الجداول. يمكنني دائمًا تعديل الفائض أو الخصائص الأخرى عبر css (أفعل ذلك في التنفيذ الحالي على أي حال). هل عنصر elementType غير وارد؟

bvaughn لا أجد أي شيء محدد حول دعم تجاوز السعة باعتباره عاملاً مقيدًا.

ربما لم أستخدم أفضل صياغة - ولكن إذا نظرت إلى Sandbox الذي ربطته بـ ( rrn61wkzwm ) ، فسترى السلوك غير المتوقع.

هذا مثال آخر هو HTML فقط: lx65871p69

يتجاهل HTMLSelectElement ( <tbody> ) الأنماط مثل height و overflow - مما يجعله عديم الفائدة للنافذة. يمكنك "إصلاح" هذا عن طريق تغيير وضع العرض الخاص به ( display: block ) ولكن هذا يلغي الغرض من استخدام HTMLTableElement لأنه يكسر سلوك تغيير حجم العمود.

يتم تقسيم سلوك تغيير حجم العمود ليبدأ في حالة استخدام الإطارات على أي حال ، لأن الحجم يعتمد على المحتوى الموجود في الأعمدة (والذي قد يتغير أثناء تمرير المستخدم).

ولكن يبدو أن عنصر القائمة الأساسي هو كل ما هو خارج اختيار المنفذ في الوقت الحالي ... هل عنصر elementType غير وارد؟

يمكنك بالفعل تحديد نوع العلامة إذا كنت تريد حقًا ( 2j0z718mwy ) على الرغم من أنني لا أرى ما

بالحديث عن نفسي وعن أي شخص قد يستخدم نافذة رد الفعل مع سيناريوهات رأس ثابتة ، سيكون من الجيد الحصول على الدعم الجدولي المتأصل المضمن في تخطيطات الجدول.

قد يكون استخدام HTMLTableElement مشكلة للأسباب التي شرحتها أعلاه. إذا كنت تريد تخطيطًا جدوليًا / شبكيًا برأس ثابت ، فيمكنك إنجاز ذلك باستخدام أحد مكونات القائمة العادية على الرغم من:

لماذا تحتاج طاولة؟ أعتقد أنه يمكنك تحقيق نفس تخطيط العمود باستخدام كتل مضمنة أو تخطيطات مرنة.

ربما يلزم وجود بنية جدول لبعض إمكانية الوصول (مثل ، قراءة شاشة أفضل مقارنةً بملفات div غير الدلالية)؟ أنا أخمن هنا.

في هذه الحالة ، سأستمر في تجاوز نمط عرض CSS وأي أنماط أخرى متأصلة في عناصر الجدول.

تجربتي في بناء مكون جدول معقد (مع عناوين ثابتة / مثبتة من أعلى وإلى اليسار ، بنية colspan / rowspan معقدة ، ونموذج بيانات لوصف الهيكل الذي يقف وراءه) منذ حوالي تسع سنوات (ثم لم يكن لدينا رد فعل ، ولا مخاوف تتعلق بإمكانية الوصول ، وبقدر ما أتذكر عدم وجود محاكاة افتراضية) هو أن زميلي الذي كان مسؤولاً عن هذا المكون حاول تنفيذه في عناصر جدول مناسبة ، وواجه صعوبة في إجبار التخطيط على التصرف بطرق معينة ، ثم قرر تنفيذ تخطيط الجدول في JavaScript خالص من divs المتوضعة والحجم تمامًا. نجح هذا الحل بشكل مثالي: لا توجد قفزات غريبة في التخطيط ، وتمرير سلس (ليس لكل صف / لكل عمود) ، وما إلى ذلك.

ربما يلزم وجود بنية جدول لبعض إمكانية الوصول (مثل ، قراءة شاشة أفضل مقارنةً بملفات div غير الدلالية)؟ أنا أخمن هنا.

يمكن استخدام أدوار الأغنية لهذا 😄

شامل للغاية ، شكرا لك. لقد أنقذتني للتو من النزول إلى حفرة الأرانب لمحاولة نموذج أولي من شأنه أن يحل مشكلة واحدة فقط لإنشاء مشاكل أخرى.

أهلا
حاولت العثور على سلسلة رسائل موجودة بدلاً من إنشاء سلسلة جديدة. أتمنى أن أكون في مكان جيد ...

هل هناك طريقة للحصول على نوع من "colspan" لدمج خليتين مقابل FixedSizeGrid (ربما يكون ذلك أكثر منطقية في السياق الخاص بي)؟
يعتمد هذا السؤال على مناقشة أخرى بدأت هنا ، ولكن لفهم أكثر ، أفضل النشر هنا.

هل هناك طريقة للحصول على نوع من "colspan" لدمج خليتين لـ FixedSizeGrid (ربما يكون له معنى أكثر في السياق الخاص بي)؟

لا. هذا غير مدعوم.

einarqBlaineBradburysompylasar في حالة ما زالت مهتمة لكم، وأنا تمكنت من الحصول على وضع النوافذ العمل مع به الجدول. في الواقع ، انتهى بي الأمر بإنشاء نافذة تفاعل التفاف مكتبة. يمكنك مشاهدة عرض توضيحي مباشر هنا: https://window-table.netlify.com/

كان السبب وراء رغبتي في استخدام علامات الجدول هو التصميم بشكل أساسي. يعد تصميم جدول html العادي أمرًا سهلاً للغاية باستخدام tw-bootstrap ، وبالتالي أردت أن أفعل الشيء نفسه مع جدول بإطارات.

إنني أميل إلى وضع علامة على Brian وأسأله ، حول ما يفكر فيه حول هذا التنفيذ (منذ أن ذكر أن علامات جدول html لن تعمل). لكنه ساعدني بالفعل بما فيه الكفاية. لذا سأترك الأمر لكم يا رفاق.

شكرا لك.

هذا نهج مثير للاهتمامpupudu. لا أعرف ما إذا كانت هناك أية مخاوف تتعلق بإمكانية الوصول لوجود علامات <table> منفصلة للعناوين والصفوف ، لكن الفكرة أنيقة بخلاف ذلك.

أحاول استخدام react-datasheet مع react-window ، فهو يعمل بشكل أساسي:

function sheetRenderer(props) {
  const Row = ({ index, style }) => (
    React.cloneElement(props.children[index], { style })
  );
  return (
    <table className={props.className}>
        <tbody>
          <FixedSizeList
              height={150}
              itemCount={1000}
              itemSize={35}
              width={300}
          >
            {Row}
          </FixedSizeList>
        </tbody>
    </table>
  )
}

export default function EntityTable(props: IEntityTableProps) {
  const initialGrid = useMemo(() => {
    return getTableGridFromCSV(props.entityListCSV);
  }, [props.entityListCSV]);
  const [modifiedGrid, updateModifiedGrid] = useImmer(initialGrid);
  return (
    <ReactDataSheet
      data={modifiedGrid}
      sheetRenderer={sheetRenderer}
      valueRenderer={cell => cell.value}
      onCellsChanged={changes => {
        updateModifiedGrid(draft => {
          changes.forEach(({ cell, row, col, value }) => {
            draft[row][col].value = value || '';
          });
        });
      }}
    />
  );
}

function getTableGridFromCSV(csv: string) {
  return csv.split('\n').map(row =>
    row.split(',').map((cell, index) => {
      if (index === 0) {
        return {
          value: cell,
          forceComponent: true,
          component: <button onClick={() => console.log(cell)}>{cell}</button>,
        };
      }
      if (index === 2) {
        return {
          value: cell,
        };
      }
      return {
        value: cell,
        component: <span>{cell}</span>,
      };
    }),
  );
}

يتم عرض المشكلة الوحيدة هي Warning: validateDOMNesting(...): <tr> cannot appear as a child of <div>. index.js:1437 Warning: validateDOMNesting(...): <div> cannot appear as a child of <tbody>.

مرحبًا ، أحاول ذلك باستخدام React-Table وألاحظ أنه يجب علي استخدام divs بدلاً من عناصر الجدول. المشكلة في ذلك هي أن مكتبات التصميم مثل material / bootstrap تعتمد على تلك العناصر. لذا فإن الأمر يتطلب الكثير من العمل لتغيير مخطط الجدول إلى divs بدلاً من عناصر الجدول. هل من الممكن على الإطلاق استخدام عناصر الجدول للفروق أو هل يجب علي إنشاء تصميمي الخاص الآن؟

simkessy ما لم تكن قد لاحظت بالفعل ، يجب عليك الخروج من نافذة الطاولة. يسمح باستخدام علامات جدول html مما يسمح لنا بإعادة استخدام الأنماط الموجودة. يجب أن تعترف بأن الجدول ليس متقدمًا مثل جدول التفاعل.
https://window-table.netlify.com/

pupudu أشيد أقرر محاولة معالجة هذا بمفردي. أردت فقط الشيء الفائق الوضوح الذي كان يبحث عنه الآخرون: هذه المكتبة ولكن مع عناصر الجدول.

تبين أنني تمكنت من تنفيذ هذا باستخدام القليل جدًا من التعليمات البرمجية ، والكثير من الإبداع. الكود بسيط بما يكفي بحيث يمكن لأي شخص نسخ / لصق وتوسيع حسب رغبته. bvaughn بعد معرفة الكيفية ، سيكون هذا تافهًا جدًا لإضافته إلى المكتبة إذا كنت تريد ، ولكن أيضًا تافهًا جدًا لتجاوزه إذا كنت تعرف كيف.

باختصار :

  • التقط النمط "العلوي" للصف الأول بعد العرض
  • قم بتخزين هذه القيمة في React.Context حتى نتمكن من تمريرها
  • قم بتطبيق القيمة على مكون جدول والذي سيكون هو ما يتم نقله ، بدلاً من الصفوف نفسها
  • أضف فتحات إضافية لأشياء مثل الرؤوس والتذييلات.
  • لا تسمح بيئة العمل في المكتبة بتمرير الأشياء بدقة ، لذا فإن React.Context هو البطل للتغلب على الاتصال عبر المكونات.

وضع حماية كود العمل: https://codesandbox.io/s/react-window-with-table-elements-d861o

رمز كمرجع

import React from 'react'
import { useState, useRef, useContext } from 'react'
import { FixedSizeList, FixedSizeListProps } from 'react-window'
import { render } from 'react-dom'

/** Context for cross component communication */
const VirtualTableContext = React.createContext<{
  top: number
  setTop: (top: number) => void
  header: React.ReactNode
  footer: React.ReactNode
}>({
  top: 0,
  setTop: (value: number) => {},
  header: <></>,
  footer: <></>,
})

/** The virtual table. It basically accepts all of the same params as the original FixedSizeList.*/
function VirtualTable({
  row,
  header,
  footer,
  ...rest
}: {
  header?: React.ReactNode
  footer?: React.ReactNode
  row: FixedSizeListProps['children']
} & Omit<FixedSizeListProps, 'children' | 'innerElementType'>) {
  const listRef = useRef<FixedSizeList | null>()
  const [top, setTop] = useState(0)

  return (
    <VirtualTableContext.Provider value={{ top, setTop, header, footer }}>
      <FixedSizeList
        {...rest}
        innerElementType={Inner}
        onItemsRendered={props => {
          const style =
            listRef.current &&
            // @ts-ignore private method access
            listRef.current._getItemStyle(props.overscanStartIndex)
          setTop((style && style.top) || 0)

          // Call the original callback
          rest.onItemsRendered && rest.onItemsRendered(props)
        }}
        ref={el => (listRef.current = el)}
      >
        {row}
      </FixedSizeList>
    </VirtualTableContext.Provider>
  )
}

/** The Row component. This should be a table row, and noted that we don't use the style that regular `react-window` examples pass in.*/
function Row({ index }: { index: number }) {
  return (
    <tr>
      {/** Make sure your table rows are the same height as what you passed into the list... */}
      <td style={{ height: '36px' }}>Row {index}</td>
      <td>Col 2</td>
      <td>Col 3</td>
      <td>Col 4</td>
    </tr>
  )
}

/**
 * The Inner component of the virtual list. This is the "Magic".
 * Capture what would have been the top elements position and apply it to the table.
 * Other than that, render an optional header and footer.
 **/
const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
  function Inner({ children, ...rest }, ref) {
    const { header, footer, top } = useContext(VirtualTableContext)
    return (
      <div {...rest} ref={ref}>
        <table style={{ top, position: 'absolute', width: '100%' }}>
          {header}
          <tbody>{children}</tbody>
          {footer}
        </table>
      </div>
    )
  }
)

/**
 * Render Our Example
 **/
render(
  <VirtualTable
    height={300}
    width="100%"
    itemCount={1000}
    itemSize={36}
    header={
      <thead>
        <tr>
          <th>Index</th>
          <th>Header 2</th>
          <th>Header 3</th>
          <th>Header 4</th>
        </tr>
      </thead>
    }
    row={Row}
    footer={
      <tfoot>
        <tr>
          <td>Footer 1</td>
          <td>Footer 2</td>
          <td>Footer 3</td>
          <td>Footer 4</td>
        </tr>
      </tfoot>
    }
  />,
  document.querySelector('main')
)

تضمين التغريدة فكرة مثيرة للاهتمام حقًا لاستخدام السياق لتحقيق ذلك. تعجبني حقيقة أنك تعرض جدولًا واحدًا فقط ، على عكس النهج الذي أتبعه حيث أعرض اثنين ، واحد للرأس والآخر للجسم. لقد تسبب هذا في الكثير من الالتباس (لم يروا ذلك tbh القادم) في مستخدمي جدول النوافذ.

سأحاول استخدام هذه الأفكار في نافذة الجدول إذا كنت لا تمانع. أعتقد أن التحدي الأكبر سيكون في معرفة كيفية ضبط حجم الصفوف تلقائيًا بناءً على المحتوى (والذي كان التحدي الأكبر للطاولة الهوائية على الأقل).

jamesmfriedman هذا يبدو واعد جدا. bvaughn هل لديك أي مخاوف بشأن هذا النهج؟

jamesmfriedman يبدو أن الرأس

إنه في الواقع ممكن ، وليس خاصًا بهذا التنفيذ. ما عليك سوى إجراء بعض عمليات البحث في googling حول الرؤوس اللاصقة باستخدام عناصر جدول HTML. أتذكر بشكل غامض أن طريقة القيام بذلك هي في الواقع جعل موضع عنصر TH لزجًا.

jamesmfriedman شكرًا جزيلاً على مثالك 👍 لقد ساعد كثيرًا marink هنا مثال على الرؤوس اللاصقة https://codesandbox.io/s/react-window-with-table-elements-jj70e تحتاج إلى إضافة style={{ position: 'sticky', top: 0 }}> إلى العلامات th

jamesmfriedman شكرا جزيلا على هذا المثال. سأبحث في استخدامه. لكنني أعتقد أن استخدام top: 0 والموضع sticky بدلاً من إعادة حساب الجزء العلوي ووجود موضع مطلق على عنصر الجدول سيكون هو السبيل للذهاب. لأنه إذا كان موضع استخدامك لزجًا للحصول على رؤوس مثبتة على العناصر رقم عشر ، فسيتم إنهاء كل شيء عند التمرير السريع.

لذا فإن السطر 79 سيكون <table style={{ top: 0, position: 'sticky', width: '100%' }}>

يؤدي ذلك أيضًا إلى إصلاح مشكلة التمرير إذا واصلت التمرير عندما تكون في الأسفل.

سبب وجيه آخر لاستخدام جداول HTML هو دعم IE11. أنا أستخدم FixedSizeList ثم نصممه باستخدام CSS-grid. ومع ذلك ، عندما تحتاج إلى إضافة ميزات أخرى مثل الأعمدة المتجاوبة والأعمدة ذات الأحجام المختلفة وما إلى ذلك ، وجعلها تعمل معًا مع IE11 ، ينتهي بك الأمر بكميات هائلة من التعليمات البرمجية. بينما تعمل جداول HTML بشكل افتراضي بدون رمز.

IE11 ليس شيئًا يجب أن تدعمه بعد الآن :)

كل مطور FE يريد الموت لـ IE11. لكن لسوء الحظ ، هناك شركات / أشخاص عالقون بها ، غير قادرين على اتخاذ الخطوة لأسباب لا يمكننا حتى تخيلها. نأمل أن تكون أمامنا بضع سنوات فقط في الوقت المناسب. حتى ذلك الحين ، سنحتاج إلى دعم IE11 ، سواء أحببنا ذلك أم لا.

لقد كانت حبة من الصعب ابتلاعها بالنسبة لي أيضًا.

@ olafur164 شكرًا على الإصلاح الذي

اسمحوا لي أن أشارك تجربتي مع التفاعل الافتراضي (حتى صفحة مشاكل نافذة رد الفعل ) وبعض مكتبة مواد واجهة المستخدم تسمى جدول المواد حيث تظهر نفس المشكلة (عناصر الجدول المختلطة بالافتراضية): https://github.com/mbrn/ مادة-جدول / قضايا / 891 # issuecomment -681986647. لا تزال هناك بعض المشكلات مثل مشاكل التصميم وتحذير validateDOMNesting(...) .

jamesmfriedman شكرًا جزيلاً على مثالك 👍 لقد ساعد كثيرًا marink هنا مثال على الرؤوس اللاصقة. تحتاج إلى إضافة style={{ position: 'sticky', top: 0 }}> إلى العلامات th

مرحبًا JCofman ، لقد جربت إصلاح CSS الخاص بك ولكنه لا يعمل معي. إليك مثال وضع الحماية للكود - https://codesandbox.io/s/react-window-with-table-elements-forked-huti6؟file=/src/index.tsx : 514-542

هناك مشكلتان -

  1. الرأس لا يلتصق بالأعلى على الرغم من وجود أنماط في مكانها.
  2. يومض / يومض الرأس أثناء التمرير بكثافة باتجاه الأعلى.
    [خطوات إعادة الإنتاج - قم بالتمرير بنسبة 50٪ لأسفل ثم قم بالتمرير السريع لأعلى ولاحظ حركة الرأس].

شكرا مقدما :)

تضمين التغريدة فكرة مثيرة للاهتمام حقًا لاستخدام السياق لتحقيق ذلك. تعجبني حقيقة أنك تعرض جدولًا واحدًا فقط ، على عكس النهج الذي أتبعه حيث أعرض اثنين ، واحد للرأس والآخر للجسم. لقد تسبب هذا في الكثير من الالتباس (لم يروا ذلك tbh القادم) في مستخدمي جدول النوافذ.

سأحاول استخدام هذه الأفكار في نافذة الجدول إذا كنت لا تمانع. أعتقد أن التحدي الأكبر سيكون في معرفة كيفية ضبط حجم الصفوف تلقائيًا بناءً على المحتوى (والذي كان التحدي الأكبر للطاولة الهوائية على الأقل).

انتهى بي الأمر بالعثور على حل مشابه جدًا لأنني أستخدم display: grid مع display: contents للصفوف ، لذلك تلتزم بشكل أساسي بقيد العناصر table > tr .

لقد استخدمت السياق + المراجع لاستدعاء طريقة داخلية ، ومع ذلك ، هذا غير ضروري تمامًا نظرًا لأنه يمكن تحقيق نفس الشيء من خلال البحث عن قيمة النمط.

const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
  function Inner({ children, ...rest }, ref) {
    const { header, footer } = useContext(VirtualTableContext)
    const {style} = children[0].props;
    return (
      <div {...rest} ref={ref}>
        <table style={style}>
          {header}
          <tbody>{children}</tbody>
          {footer}
        </table>
      </div>
    )
  }
)

يتم توفير خاصية النمط بواسطة المكتبة عندما تقوم بتنفيذ createElement لكل صف ، وبما أن مكون Row الخاص بك لا يقوم بتعيين style إلى tr ، فأنت لست كذلك تمريرهم إما.

مؤخرًا ، كنت أتساءل عن شيء كهذا. ماذا لو نقلنا جسم الجدول بالكامل باستخدام حشوة باستخدام عناصر زائفة (بعد / قبل) عبر خصائص css المخصصة 🤔

في المثال باستخدام رد الفعل الافتراضي يكون https://codesandbox.io/s/poc-react-virtual-table-jyz0m

كنت في حاجة ماسة إلى جدول حتى أتمكن من تحقيق تجربة المستخدم التي أردتها ولم أكن راضيًا عن الحلول لجعلها تعمل مع react-window .

انتهى بي الأمر فقط إلى استخلاص منطق التدوير بنفسي وإدخاله في جدولين ، أحدهما للعناوين والثاني للمحتوى ، على غرار ما تم نشره أعلاه. يتمثل الاختلاف في أسلوبي في أن الجدول الثاني لا يزال يحتوي على رؤوس في الترميز ولكنه مخفي بصريًا بحيث يظل متاحًا ، في حين أن رؤوس الأول كانت موجودة فقط للمستخدمين المبصرين ومثبتة في الموضع .. عملت مثل السحر ، و كان الرمز أبسط بشكل كبير.

مجرد رميها هناك في حالة رغبة شخص ما في تجربة ذلك.

piecyk هذا رائع ، مشابه جدًا لكيفية تطبيق https://virtuoso.dev/grouped-by-first-letter/

لا بد لي من إضافة أن وضع الحاوية بأكملها مع المطلق / العلوي هو الأداء ، ولكن تشغيل تدقيق الكمال مع Chrome أرى مشاكل CLS التي قد تؤثر على FPS. لا أعتقد أن التأثير ملحوظ ، يمكنك أن ترى مدى السرعة والسلاسة في هذا المثال: https://b6udg.csb.app/ (على الرغم من أنها حاوية كبيرة الحجم). ولكن مع الحشو أعلى / أسفل لا يوجد CLS!

سأحاول هذا بنفسي وقياس الفرق في وقت قريب.

pupudu أشيد أقرر محاولة معالجة هذا بمفردي. أردت فقط الشيء الفائق الوضوح الذي كان يبحث عنه الآخرون: هذه المكتبة ولكن مع عناصر الجدول.

تبين أنني تمكنت من تنفيذ هذا باستخدام القليل جدًا من التعليمات البرمجية ، والكثير من الإبداع. الكود بسيط بما يكفي بحيث يمكن لأي شخص نسخ / لصق وتوسيع حسب رغبته. bvaughn بعد معرفة الكيفية ، سيكون هذا تافهًا جدًا لإضافته إلى المكتبة إذا كنت تريد ، ولكن أيضًا تافهًا جدًا لتجاوزه إذا كنت تعرف كيف.

_القصور _:

  • التقط النمط "العلوي" للصف الأول بعد العرض
  • قم بتخزين هذه القيمة في React.Context حتى نتمكن من تمريرها
  • قم بتطبيق القيمة على مكون جدول والذي سيكون هو ما يتم نقله ، بدلاً من الصفوف نفسها
  • أضف فتحات إضافية لأشياء مثل الرؤوس والتذييلات.
  • لا تسمح بيئة العمل في المكتبة بتمرير الأشياء بدقة ، لذا فإن React.Context هو البطل للتغلب على الاتصال عبر المكونات.

وضع حماية كود العمل: https://codesandbox.io/s/react-window-with-table-elements-d861o

رمز كمرجع

import React from 'react'
import { useState, useRef, useContext } from 'react'
import { FixedSizeList, FixedSizeListProps } from 'react-window'
import { render } from 'react-dom'

/** Context for cross component communication */
const VirtualTableContext = React.createContext<{
  top: number
  setTop: (top: number) => void
  header: React.ReactNode
  footer: React.ReactNode
}>({
  top: 0,
  setTop: (value: number) => {},
  header: <></>,
  footer: <></>,
})

/** The virtual table. It basically accepts all of the same params as the original FixedSizeList.*/
function VirtualTable({
  row,
  header,
  footer,
  ...rest
}: {
  header?: React.ReactNode
  footer?: React.ReactNode
  row: FixedSizeListProps['children']
} & Omit<FixedSizeListProps, 'children' | 'innerElementType'>) {
  const listRef = useRef<FixedSizeList | null>()
  const [top, setTop] = useState(0)

  return (
    <VirtualTableContext.Provider value={{ top, setTop, header, footer }}>
      <FixedSizeList
        {...rest}
        innerElementType={Inner}
        onItemsRendered={props => {
          const style =
            listRef.current &&
            // @ts-ignore private method access
            listRef.current._getItemStyle(props.overscanStartIndex)
          setTop((style && style.top) || 0)

          // Call the original callback
          rest.onItemsRendered && rest.onItemsRendered(props)
        }}
        ref={el => (listRef.current = el)}
      >
        {row}
      </FixedSizeList>
    </VirtualTableContext.Provider>
  )
}

/** The Row component. This should be a table row, and noted that we don't use the style that regular `react-window` examples pass in.*/
function Row({ index }: { index: number }) {
  return (
    <tr>
      {/** Make sure your table rows are the same height as what you passed into the list... */}
      <td style={{ height: '36px' }}>Row {index}</td>
      <td>Col 2</td>
      <td>Col 3</td>
      <td>Col 4</td>
    </tr>
  )
}

/**
 * The Inner component of the virtual list. This is the "Magic".
 * Capture what would have been the top elements position and apply it to the table.
 * Other than that, render an optional header and footer.
 **/
const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
  function Inner({ children, ...rest }, ref) {
    const { header, footer, top } = useContext(VirtualTableContext)
    return (
      <div {...rest} ref={ref}>
        <table style={{ top, position: 'absolute', width: '100%' }}>
          {header}
          <tbody>{children}</tbody>
          {footer}
        </table>
      </div>
    )
  }
)

/**
 * Render Our Example
 **/
render(
  <VirtualTable
    height={300}
    width="100%"
    itemCount={1000}
    itemSize={36}
    header={
      <thead>
        <tr>
          <th>Index</th>
          <th>Header 2</th>
          <th>Header 3</th>
          <th>Header 4</th>
        </tr>
      </thead>
    }
    row={Row}
    footer={
      <tfoot>
        <tr>
          <td>Footer 1</td>
          <td>Footer 2</td>
          <td>Footer 3</td>
          <td>Footer 4</td>
        </tr>
      </tfoot>
    }
  />,
  document.querySelector('main')
)

شكرًا لك على هذا ، هل حاول أي شخص (بنجاح) استخدام هذا مع المكون InfiniteLoader ؟ ... لقد حاولت التخلص منه ولكني أواجه مشكلات مع "الغلاف" الداخلي ، والذي نفترض أن المحمل اللانهائي يمرر دعائم غير متوقعة إلى النوع الداخلي.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات