मैंने रिएक्शन-डंड लागू किया फुल डोम कंट्रोल के साथ रिएक्ट के लिए रिएक्ट , एक लचीला एचटीएमएल 5 ड्रैग-एंड-ड्रॉप मिक्सिन लागू किया।
मौजूदा ड्रैग-एंड-ड्रॉप लाइब्रेरीज़ मेरे उपयोग के मामले में फिट नहीं थीं इसलिए मैंने अपना लिखा। यह उस कोड के समान है जिसे हम Stampsy.com पर लगभग एक साल से चला रहे हैं, लेकिन रिएक्ट और फ्लक्स का लाभ उठाने के लिए फिर से लिखा गया है।
मेरे पास प्रमुख आवश्यकताएं:
- शून्य डोम या सीएसएस का स्वयं का उत्सर्जन करें, इसे उपभोग करने वाले घटकों के लिए छोड़ दें;
- खपत करने वाले घटकों पर जितना संभव हो उतना कम संरचना का प्रस्ताव;
- एचटीएमएल 5 को प्राथमिक बैकेंड के रूप में खींचें और छोड़ें, लेकिन भविष्य में अलग-अलग बैकेंड जोड़ना संभव बना सकते हैं;
- मूल HTML5 एपीआई की तरह, डेटा को खींचने पर जोर देना और न कि केवल "ड्रैग करने योग्य विचार";
- उपभोग कोड से एचटीएमएल 5 एपीआई को छिपाएं;
- विभिन्न प्रकार के डेटा के लिए विभिन्न घटक "ड्रैग सोर्स" या "ड्रॉप टारगेट" हो सकते हैं;
- एक घटक को कई ड्रैग सोर्स रखने और जरूरत पड़ने पर लक्ष्य छोड़ने की अनुमति दें;
- यदि संगत डेटा को खींचा जा रहा है या होवर किया गया है, तो उनकी उपस्थिति को बदलने के लिए ड्रॉप लक्ष्य बनाना आसान बनाएं;
- ब्राउज़र स्क्रीनशॉट को दरकिनार करते हुए, तत्व स्क्रीनशॉट के बजाय ड्रैग थंबनेल के लिए छवियों का उपयोग करना आसान बनाएं।
यदि ये ध्वनि आपको परिचित हैं, तो पढ़ें।
प्रयोग
सरल खींचें स्रोत
सबसे पहले, उन प्रकार के डेटा की घोषणा करें जिन्हें खींचा जा सकता है।
इनका उपयोग ड्रैग सोर्स और ड्रॉप टारगेट की "अनुकूलता" जांचने के लिए किया जाता है:
// ItemTypes.js
module.exports = {
BLOCK: 'block',
IMAGE: 'image'
};
(यदि आपके पास एकाधिक डेटा प्रकार नहीं हैं, तो यह परिवाद आपके लिए नहीं हो सकता है।)
फिर, चलो एक बहुत ही सरल ड्रैग करने योग्य घटक बनाते हैं, जब घसीटा जाता है, प्रतिनिधित्व करता है IMAGE
:
var { DragDropMixin } = require('react-dnd'),
ItemTypes = require('./ItemTypes');
var Image = React.createClass({
mixins: [DragDropMixin],
configureDragDrop(registerType) {
// Specify all supported types by calling registerType(type, { dragSource?, dropTarget? })
registerType(ItemTypes.IMAGE, {
// dragSource, when specified, is { beginDrag(), canDrag()?, endDrag(didDrop)? }
dragSource: {
// beginDrag should return { item, dragOrigin?, dragPreview?, dragEffect? }
beginDrag() {
return {
item: this.props.image
};
}
}
});
},
render() {
// {...this.dragSourceFor(ItemTypes.IMAGE)} will expand into
// { draggable: true, onDragStart: (handled by mixin), onDragEnd: (handled by mixin) }.
return (
<img src={this.props.image.url}
{...this.dragSourceFor(ItemTypes.IMAGE)} />
);
}
);
निर्दिष्ट करके configureDragDrop
, हम DragDropMixin
इस घटक के ड्रैग-ड्रॉप व्यवहार को बताते हैं। ड्रैग करने योग्य और टपकने वाले दोनों घटक एक ही मिश्रण का उपयोग करते हैं।
अंदर configureDragDrop
, हमें registerType
अपने प्रत्येक कस्टम के लिए कॉल करना होगा ItemTypes
जो घटक का समर्थन करता है। उदाहरण के लिए, आपके ऐप में छवियों के कई प्रतिनिधित्व हो सकते हैं, और प्रत्येक एक के dragSource
लिए प्रदान करेगाItemTypes.IMAGE
।
A dragSource
सिर्फ एक ऑब्जेक्ट है जो निर्दिष्ट करता है कि ड्रैग सोर्स कैसे काम करता है। आपको beginDrag
उस आइटम को वापस लागू करना होगा जो आपके द्वारा खींचे जा रहे डेटा का प्रतिनिधित्व करता है और, वैकल्पिक रूप से, कुछ विकल्प जो ड्रैगिंग UI को समायोजित करते हैं। आप वैकल्पिक रूप canDrag
से ड्रैग करने, या endDrag(didDrop)
ड्रॉप होने (या नहीं) होने पर कुछ लॉजिक निष्पादित करने के लिए मना कर सकते हैं । और आप घटकों के बीच इस तर्क dragSource
को उनके लिए एक साझा मिश्रण उत्पन्न करके साझा कर सकते हैं।
अंत में, आपको ड्रैग हैंडलर संलग्न करने के लिए {...this.dragSourceFor(itemType)}
कुछ (एक या अधिक) तत्वों पर उपयोग करना होगा render
। इसका मतलब है कि आपके पास एक तत्व में कई "ड्रैग हैंडल" हो सकते हैं, और वे विभिन्न प्रकार के आइटम के अनुरूप भी हो सकते हैं। (यदि आप JSX Spread Attributes Synax से परिचित नहीं हैं , तो इसे देखें)।
सरल ड्रॉप लक्ष्य
मान लीजिए कि हम s के ImageBlock
लिए एक टारगेट बनना चाहते हैं IMAGE
। यह बहुत अधिक समान है, सिवाय इसके कि हमें registerType
एक dropTarget
कार्यान्वयन देने की आवश्यकता है :
var { DragDropMixin } = require('react-dnd'),
ItemTypes = require('./ItemTypes');
var ImageBlock = React.createClass({
mixins: [DragDropMixin],
configureDragDrop(registerType) {
registerType(ItemTypes.IMAGE, {
// dropTarget, when specified, is { acceptDrop(item)?, enter(item)?, over(item)?, leave(item)? }
dropTarget: {
acceptDrop(image) {
// Do something with image! for example,
DocumentActionCreators.setImage(this.props.blockId, image);
}
}
});
},
render() {
// {...this.dropTargetFor(ItemTypes.IMAGE)} will expand into
// { onDragEnter: (handled by mixin), onDragOver: (handled by mixin), onDragLeave: (handled by mixin), onDrop: (handled by mixin) }.
return (
<div {...this.dropTargetFor(ItemTypes.IMAGE)}>
{this.props.image &&
<img src={this.props.image.url} />
}
</div>
);
}
);
खींचें स्रोत + ड्रॉप लक्ष्य एक घटक में
मान लें कि अब हम चाहते हैं कि उपयोगकर्ता एक छवि को बाहर निकालने में सक्षम हो ImageBlock
। हमें बस dragSource
इसमें और कुछ हैंडलर जोड़ने की आवश्यकता है :
var { DragDropMixin } = require('react-dnd'),
ItemTypes = require('./ItemTypes');
var ImageBlock = React.createClass({
mixins: [DragDropMixin],
configureDragDrop(registerType) {
registerType(ItemTypes.IMAGE, {
// Add a drag source that only works when ImageBlock has an image:
dragSource: {
canDrag() {
return !!this.props.image;
},
beginDrag() {
return {
item: this.props.image
};
}
}
dropTarget: {
acceptDrop(image) {
DocumentActionCreators.setImage(this.props.blockId, image);
}
}
});
},
render() {
return (
<div {...this.dropTargetFor(ItemTypes.IMAGE)}>
{/* Add {...this.dragSourceFor} handlers to a nested node */}
{this.props.image &&
<img src={this.props.image.url}
{...this.dragSourceFor(ItemTypes.IMAGE)} />
}
</div>
);
}
);
क्या संभव है?
मैंने सब कुछ कवर नहीं किया है लेकिन इस API का उपयोग कुछ और तरीकों से करना संभव है:
- का उपयोग करें
getDragState(type)
औरgetDropState(type)
यदि खींच सक्रिय है और इसका इस्तेमाल सीएसएस वर्ग या गुण टॉगल करने के लिए सीखने के लिए;
- निर्दिष्ट
dragPreview
होना करने के लिए Image
खींचें प्लेसहोल्डर के रूप में छवियों (उपयोग का उपयोग करने के ImagePreloaderMixin
लिए उन्हें लोड करने के लिए);
- कहते हैं, हम
ImageBlocks
पुन: प्रयोज्य बनाना चाहते हैं । हम केवल उन्हें लागू करने की जरूरत है dropTarget
और dragSource
के लिए ItemTypes.BLOCK
।
- मान लीजिए कि हम अन्य प्रकार के ब्लॉक जोड़ते हैं। हम उनके पुनः तर्क तर्क को मिक्सी में रखकर पुनः उपयोग कर सकते हैं।
dropTargetFor(...types)
कई प्रकारों को एक साथ निर्दिष्ट करने की अनुमति देता है, इसलिए एक ड्रॉप ज़ोन कई अलग-अलग प्रकारों को पकड़ सकता है।
- जब आपको अधिक महीन दाने वाले नियंत्रण की आवश्यकता होती है, तो अधिकांश तरीकों को ड्रैग इवेंट पास किया जाता है जो उन्हें अंतिम पैरामीटर के रूप में उत्पन्न करता है।
अप-टू-डेट प्रलेखन और स्थापना निर्देशों के लिए, सिर के लिए प्रतिक्रिया- dnd रेपो गितुब पर ।