React-dnd: دعم سحب عناصر متعددة

تم إنشاؤها على ٢٥ أكتوبر ٢٠١٤  ·  30تعليقات  ·  مصدر: react-dnd/react-dnd

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

screen shot 2014-10-26 at 1 07 07

نظرًا لأن العناصر المسحوبة المتعددة قد لا تكون أشقاء في DOM و setDragImage(element, x, y) حد كبير مجنون ولم تتحسن ، فلن نثقل كاهل أنفسنا بمحاولة عرض عدة عناصر في معاينة السحب في وقت واحد.

كيف يمكننا المساعدة في تنفيذ هذا السيناريو ، إذا لم نتمكن من إظهار معاينة السحب "المتعدد"؟

بطريقة ما ، هذا السيناريو ممكن بالفعل: يمكن للمستهلكين تتبع العناصر المحددة يدويًا ، وتعيين dragPreview إلى نوع من العنصر النائب العام Image والتفاعل بشكل مناسب مع إسقاط (بقدر ما يتعلق بالأعمال التجارية) المنطق معني) عدة عناصر.

ومع ذلك ، لا توجد حاليًا طريقة مدعومة لأحد العناصر لمعرفة أنه جزء من مجموعة يتم سحبها. من وجهة نظر React-dnd ، إذا سحبنا شيئًا ما ، فإن هذا المكون يحصل على getDragState(type).isDragging = true ، لكن المكونات الأخرى لا تفعل ذلك. من وجهة نظر تطبيقك ، إذا كنت تدعم التحديد المتعدد ، فأنت تريد أن تدرك جميع العناصر "المحددة" منطقيًا أنه يتم سحبها ، حتى لو تم سحب عنصر واحد فقط منها بالفعل.

ما نحتاجه هو طريقة للمكونات لإخبار رد الفعل بأنه ، "مهلاً ، على الرغم من أن onDragStart تم تلقيه بواسطة مكون آخر ، أريد أن أتظاهر بأنني أتعرض للسحب أيضًا ، ولدي getDragState(type) mirror بسحب المكون getDragState(type) ، وتم استدعاء endDrag(didDrop) أيضًا حتى أتمكن من القيام بأشياءي ".

كيف ستختار المكونات ذلك؟

design decisions

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

إذا كان أي شخص مهتمًا ، فقد قمت بتنفيذ عرض سحب / شبكة متعدد: https://codesandbox.io/s/9j897k0mwy.
يمكنك استخدام مفاتيح cmd / ctrl و shift لتحديد عناصر متعددة ، ثم سحبها حول الشبكة وإدراجها في أي مكان.

لا يزال هذا عرضًا توضيحيًا ، لكن يمكنني تجريد الكود أكثر قليلاً وحزمه في مكون لاحقًا.

ال 30 كومينتر

ليست أولوية. يمكننا إعادة الزيارة بعد إدخال مفاتيح مصدر السحب (https://github.com/gaearon/react-dnd/issues/38#issuecomment-73409935).

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

كندة.

أولاً نتعلم تمرير قيمة خالية component (مطلوب لـ # 38) ومكون مختلف بنفس key (مطلوب لـ # 53).

ثم نضيف groupKey وهو اختياري. مثل key ، يتم تحديده في مصدر السحب وهو عبارة عن سلسلة. عندما تبدأ في سحب شيء ما بـ groupKey ، سنتصل بـ beginDrag ليس فقط على المتصل ، ولكن على كل مصدر سحب مثبت بنفس groupKey ، ونجمع عناصرهم في مجموعة. سنقوم بتمرير هذه العناصر بدلاً من item لإسقاط الطرق المستهدفة. عند انتهاء السحب ، سنقوم باستدعاء acceptDrop عند هدف الإسقاط مع مصفوفة عنصر ، ثم نقوم باستدعاء كل مصدر سحب endDrag مع العنصر الخاص به.

الأمر الممتع هو أنه يمكننا رسم DragLayer باستخدام مكون مصغر مخصص "مركب" وعداد مثل لقطة الشاشة أعلاه لأننا نعرف العدد من items.length .

هذه فكرة أقل بشاعة مما كنت أفكر فيه

: +1: لهذه الميزة :-)

الخاتمة ، لأنني لا أمتلك حاليًا حالة استخدام لهذا ، وهي جهد تنفيذ كبير.

تضمين التغريدة

لقد استخدمت Java / Swing DnD مرة أخرى في اليوم ، وربما كان لديهم جيش من المطورين الذين تصارعوا مع هذه المشكلة وتوصلوا إلى إطار عمل مرن وعامة للغاية ومُحسَّن للغاية. أوصي بالبحث في أطر عمل سطح المكتب القديمة لأنها على الأرجح قد حلت جميع التحديات الصعبة من خلال إنشاء إطار عمل DnD جيد مثل هذا.

كانت طريقة القيام بذلك في Java / Swing (على الرغم من عدم وجود دعم مدمج لسحب الصور) هي جعل عرض الشجرة نفسه مصدر السحب _ وجعله _ قادرًا على تحديد ما إذا كان يجب بدء السحب بناءً على الحالة الحالية وموقف بدء السحب_. هل يتوفر monitor.getInitialSourceClientOffset() عند استدعاء canDrag و beginDrag ؟ سيريد الناس بالتأكيد أن يكون متاحًا. ربما يريدون أيضًا أن تكون مفاتيح التعديل (ctrl ، alt ، shift) متاحة وأن يكونوا قادرين على جعل مصادر السحب تحدد ما إذا كان سيتم نقل الأهداف أو نسخها ، وإسقاط الأهداف لتحديد ما إذا كانت تدعم النقل و / أو النسخ ، بناءً على أي من هذه العوامل ، لأن ذلك ممكن في Java / Swing وأنا أخمن أطر عمل أخرى. يحتوي Swing أيضًا على مفهوم _ أدوات التعرف على إيماءات السحب_ التي يمكن تبديلها.

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

ضع في اعتبارك أيضًا أن أحد المطورين قد يرغب في تغيير ترتيب العناصر التي يتم سحبها بناءً على العنصر الذي نقر المستخدم وسحب منه. - أعتقد أن مستكشف Windows يتصرف بهذه الطريقة.

هل قام أي شخص بتنفيذ سحب عناصر متعددة باستخدام رد الفعل-dnd في تطبيقاته؟ ما هو الحل الحالي الخاص بك لهذا؟

هل تقصد هدف إسقاط متعدد لمصدر سحب واحد؟

+1 @ danii1 : هل قام أي شخص بتنفيذ سحب عناصر متعددة؟

قمت بتطبيقه ، الحل هو في الأساس ما تم وصفه في التدوينة الأولى:

  1. تتبع العناصر التي اخترتها
  2. تنفيذ CustomDragLayer (راجع https://gaearon.github.io/react-dnd/docs-drag-layer.html) وعرض العناصر المحددة بنفسك
  3. انخفاض المقبض إذا كان العنصر الذي تم إسقاطه جزءًا من التحديد

لقد نفذته من خلال:

  1. تتبع العناصر المحددة في مجموعة
  2. قم بتمرير هذا كخاصية إلى مصدر dnd
  3. في startDrag ، قم باسترداد مجموعة من الدعائم وإعادتها كعنصر السحب
  4. إنشاء معاينة السحب المخصصة
  5. عند EndDrag ، انقل جميع العناصر الموجودة في المجموعة إلى الهدف dnd

لدي حالة استخدام مختلفة قليلاً لهذا على ما أعتقد ، أريد أن أرسم عقدًا قابلة للسحب بحواف غير قابلة للسحب ولكنها تتحرك عندما يتم إرفاق العقد لنقلها. تطبيقي الحالي هو CustomDragLayer الذي يرسم الحواف عندما يكتشف أن DraggableNode يتحرك (مرسوم أيضًا على CustomDragLayer لكنني أعتقد أنه قد يكون من الأفضل تصميمه على أنه وضع السحب المتعدد عن طريق تنفيذ جميع الحواف مثل DragSources مع isDragging() تنفيذه لاكتشاف ما إذا كانت العقدة التي تم ربطها بها تتحرك حتى يتمكنوا من رسم أنفسهم بدلاً من إدخال الإحداثيات على شكل دعائم CustomDragLayer .

@ danii1
هل يمكنك مشاركة ما قمت بتطبيقه كمرجع

سأكتب منشورًا وأضيف الريبو حول السحب والإفلات المتعدد والمتداخلين باستخدام رد فعل-dnd + إعادة.

nayemmajhar ، سيكون رائعًا

nayemmajhar أي تحديث على مثال بهذا؟

لقد قمت بتطوير هذا التطبيق باستخدام رد فعل DnD مع reduxJS منذ فترة طويلة https://www.joomshaper.com/page-builder أنا أكتب درسًا تعليميًا ولكني بحاجة إلى وقت للنشر

serle هل ستتمكن من مشاركة مثال رمز لكيفية القيام بذلك؟

@ ianmclean2011 تحقق من ذلك هنا: https://github.com/react-dnd/react-dnd/issues/590

أحاول تنفيذ السحب المتعدد في مثال مشابه للمثال القابل للفرز هنا: https://react-dnd.github.io/react-dnd/examples-sortable-simple.html. أريد أن أكون قادرًا على تحديد أي كائنات ، ثم نقلها كوحدة لأعلى ولأسفل القائمة. أواجه مشكلة في الالتفاف حول كيفية استخدام الأمثلة / المعلومات التي تمت مشاركتها أعلاه للقيام بذلك. هل لديك أي أفكار / أفكار / ملاحظات حول كيفية عمل ذلك؟

إذا كان أي شخص مهتمًا ، فقد قمت بتنفيذ عرض سحب / شبكة متعدد: https://codesandbox.io/s/9j897k0mwy.
يمكنك استخدام مفاتيح cmd / ctrl و shift لتحديد عناصر متعددة ، ثم سحبها حول الشبكة وإدراجها في أي مكان.

لا يزال هذا عرضًا توضيحيًا ، لكن يمكنني تجريد الكود أكثر قليلاً وحزمه في مكون لاحقًا.

melvynhills هل بحثت في حل لا يتطلب تمرير جميع البطاقات المحددة إلى كل مكون من مكونات البطاقة؟ لا أعتقد أن هناك حلًا بالنظر إلى أن startDrag () للبطاقة تحتاج إلى مرجع لجميع البطاقات المحددة.

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

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

@ jedwards1211 هل تعتقد أن هذا ممكن مع هذه المكتبة؟ خاصة حالة الاستخدام لبدء سحب عنصر لم يتم تحديده قبل بدء السحب. لست متأكدًا من أنها الطريقة التي من المفترض أن يعمل بها رد الفعل.

هل قام أي شخص بحل الحالة التي يوجد فيها أهداف إسقاط متعددة؟
لنفترض أن أحدهما يقوم بسحب عناصر متعددة (باستخدام أحد الحلول أعلاه) وينتهي أحد العناصر بنوع واحد من هدف الإسقاط والآخر على عنصر مختلف. سيتم تشغيل drop لمصدر السحب الذي بدأ السحب فقط ، ولكن ليس للمصدر الآخر. أي أفكار حول كيفية تشغيل الإسقاط بشكل فردي لكل عنصر يتم نقله.
مثال:
Is development slow, Online Whiteboard for Visual Collaboration 2019-11-27 10-45-33

تحرير: تم إنشاء مشكلة منفصلة لهذا واحد https://github.com/react-dnd/react-dnd/issues/1650

من المحتمل أن mousedown بتشغيل اختيار العنصر (وهو ما يجب أن تفعله ، جميع البرامج التي تستخدم DnD التي استخدمتها تعمل بهذه الطريقة) ، فستعمل بشكل جيد مع React DnD لكي يكون مكون الحاوية هو السحب المصدر ، لأن أحداث السحب ستأتي بعد mousedown .

هل بحثت في حل لا يتطلب تمرير جميع البطاقات المحددة لكل مكون بطاقة؟

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

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

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