1. Causes et idées
J'ai toujours voulu écrire un effet glisser-déposer natif en js, et je me suis amusé à apprendre à réagir récemment. J'ai donc utilisé React pour obtenir cet effet glisser-déposer.
Tout d’abord, l’idée de l’effet glisser est en fait très simple. Il y a principalement trois étapes :
1. Lorsque vous êtes sur la souris, démarrez l'événement déplaçable et enregistrez les paramètres de coordonnées d'origine de l'élément déplacé.
2. Lors du déplacement de la souris, enregistrez la distance déplacée par la souris en temps réel, puis calculez et définissez la nouvelle valeur de coordonnées en fonction des paramètres de coordonnées de la première étape de l'élément déplacé.
3. Pendant onmouseup, fermez l'événement déplaçable et enregistrez la nouvelle valeur de coordonnée.
Remarque : La position de l'élément est principalement déterminée par le positionnement absolu du haut et de la gauche, donc le CSS de l'élément déplacé doit être défini sur le positionnement absolu.
2. Outils auxiliaires
Les outils auxiliaires rendent principalement le processus de développement efficace et cool. Dans cette démo, je voudrais recommander à tout le monde un outil de développement gulp+browser-sync. Dans cette démo, la fonction principale de gulp est de configurer la compilation en temps réel de fichiers jsx en réaction. , si vous écrivez du CSS, c'est sass, et vous pouvez également configurer une compilation en temps réel de sass. En utilisant la synchronisation du navigateur, l'essentiel est d'actualiser automatiquement la page en temps réel. Lorsque nous créons habituellement des pages et voyons l'effet, nous actualisons généralement le navigateur via F5, puis voyons la page. Mais avec ce plug-in, lorsque vous avez fini d'écrire le code, appuyez simplement sur ctrl+s pour enregistrer, et le nouvel effet s'actualisera automatiquement dans le navigateur, et vous pourrez alors le voir.
Explication détaillée de l'utilisation :
Installation :
1. Installez gulp dans l'environnement de nœud. Je n'entrerai pas dans les détails ici. Pour le processus spécifique, veuillez vous référer à mon article de blog "Ce que vous devez savoir pour démarrer avec React.js"
2. Pour installer gulp-livereload, sur la ligne de commande ou git bash, saisissez npm install --save-dev gulp-livereload
3. Installez gulp-watch, sur la ligne de commande ou git bash, entrez npm install --save-dev gulp-watch
4. Pour installer la synchronisation du navigateur, sur la ligne de commande ou sur git bash, entrez npm install --save-dev browser-sync
La configuration et l'explication sont telles qu'indiquées sur la figure :
3. Page de définition de la construction des composants
Remarque : les instructions de code ici sont toutes fournies après l'installation des modules liés à React. Pour le processus d'installation, veuillez consulter mon article de blog "Ce que vous devez savoir pour démarrer avec React.js".
Rendu :
Idées de fractionnement de composants :
J'ai pensé qu'il serait préférable de diviser les composants en parties plus petites, j'ai donc créé respectivement l'entrée et le bouton en un seul composant :
var React=require('react'); var MyInput=React.createClass({ render:function(){ return ( <div className="form-group"> <label htmlFor={this.props.labelId} className="col-sm-2 control-label{this.props.labelTip</label> <div className="col-sm-10"> <input name={this.props.name} type={this.props.type} onChange={this.props.onChange} className="form-control" id={this.props.labelId} placeholder={this.props.placeholder}/> </div> </div> ); } }); module.exports=MyInput;
var React=require('react'); var Button=React.createClass({ render:function(){ return ( <button type={this.props.type} className="loginButton">{this.props.ButtonTip}</button> ); } }) module.exports=Button;
Comme il y a beaucoup d'entrées qui doivent être spécifiées, dans ce cas, si vous le définissez comme moi, vous devez passer trop de paramètres, et en fait, la plupart des entrées connectées sont fixes et il n'est pas nécessaire pour les réutiliser, ce n'est donc pas une bonne idée. Il est préférable d'écrire l'entrée directement ici.
Le composant parent après écriture :
render:function(){ return ( <form className="form-horizontal" id="form" ref="dragBox" onSubmit={this.submitHandler} onMouseMove={this.move} onMouseUp={this.endDrag}> <DragArea callbackParent={this.onChildChanged} /> <div id="form-wrap"> <MyInput name="username" labelId={"userId"} labelTip={"用户名"} type={"text"} placeholder={"请输入用户名"} value={this.state.username} onChange={this.handleChange}/> <MyInput name="password" labelId={"pw"} labelTip={"密码"} type={"password"} placeholder={"请输入密码"} value={this.state.password} onChange={this.handleChange}/> <div className="form-group"> <div className="col-sm-offset-2 col-sm-10"> <div className="checkbox"> <label> <input name="checked" type="checkbox" checked={this.state.checked} onChange={this.handleChange} /> 记住我 </label> </div> </div> </div> <MyButton type={"submit"} ButtonTip={"登陆"}/> </div> </form> );
Remarque : étant donné que le véritable nœud dom doit être obtenu dans la démo, ref est défini.
Ajoutez le style CSS et la page est terminée ! Enfin, voici le point ! ! !
4. Communication entre les composants parent et enfant pour implémenter le glisser-déposer
Remarque : Puisque l'effet que je souhaite obtenir est que lorsque la souris est enfoncée sur le sous-composant DragArea, le formulaire entier est déplacé, donc le DragArea commence le glissement et le formulaire répond. Par conséquent, certaines propriétés d'état du composant parent doivent être transmises au composant enfant au début. Ensuite, lorsque la souris est enfoncée sur le DragArea, les paramètres de coordonnées d'origine du composant parent doivent être retrouvés via le composant enfant DragArea, puis le composant enfant. Les propriétés d'état du composant parent doivent être mises à jour et indiquent au composant parent que le glissement est disponible. Les paramètres transmis du composant parent au composant enfant sont transmis directement. Le composant enfant doit transmettre des événements pour transmettre des paramètres au composant parent. Définissez donc une telle fonction dans le composant parent :
onChildChanged:function(newState){ //因为参数过多,所以把参数放到对象里面,通过对象来传 this.setState(newState); },
Le sous-composant doit lier cette fonction, comme le code ci-dessus : callbackParent={this.onChildChanged}
Dans le composant enfant, la fonction de réponse est :
startDrag:function(e){ var dragBox=document.getElementById('form'); var newState={}; var event=e||window.event; event.preventDefault(); var computedStyle=document.defaultView.getComputedStyle(dragBox,null); newState.left=computedStyle.left; newState.top=computedStyle.top; newState.currentX=event.clientX; newState.currentY=event.clientY; newState.flag=true; <span style="color: #0000ff;"> this.props.callbackParent(newState);</span> }
De cette façon, le commutateur glisser est activé dans le sous-composant, et les paramètres pertinents de from ont été mis à jour. Les deux autres événements de from, move et endDrag, sont :
.move:function(event){ var e = event ? event : window.event; //兼容IE的写法 if (this.state.flag) { var nowX = e.clientX, nowY = e.clientY; var disX = nowX - this.state.currentX, disY = nowY - this.state.currentY; ReactDOM.findDOMNode(this.refs.dragBox).style.left = parseInt(this.state.left) + disX + "px"; ReactDOM.findDOMNode(this.refs.dragBox).style.top = parseInt(this.state.top) + disY + "px"; } }, endDrag:function(){ var computedStyle=document.defaultView.getComputedStyle(ReactDOM.findDOMNode(this.refs.dragBox),null); this.setState({ left:computedStyle.left, top:computedStyle.top, flag:false }); }
Pada ketika ini, seret dan lepas dilaksanakan!
5. Refleksi
1. Secara teorinya, kesan seretan boleh direalisasikan dalam mana-mana elemen, dan idea seret adalah sama, jadi secara teorinya, fungsi setiap proses seretan boleh diekstrak dan dijadikan Mixin, dan kemudian Boleh dipanggil berulang kali. Ini adalah idea awal saya, tetapi saya sentiasa membuat kesilapan apabila menghantar parameter, bertindak balas dan elemen mengikat. Selepas mencari maklumat, saya tidak dapat mencari maklumat tentang kaedah penulisan mudah bertindak balas dan seret dan lepas Hanya terdapat beberapa pemalam khas untuk bertindak balas, dan ia ditulis dalam ES6 saya tidak dapat memahaminya tahap. Jadi saya tinggalkan cara penulisan ini buat sementara waktu. Saya harap pakar yang mempunyai idea yang berkaitan boleh berkongsi dengan saya.
2. Apabila subkomponen dalam artikel memperoleh parameter daripada, ia menggunakan var dragBox=document.getElementById('form'); Tetapi saya tidak begitu biasa dengan cara mendapatkan dom komponen induk daripada komponen anak. Saya telah cuba mentakrifkan refs=this.refs.dragBox dalam komponen induk. Kemudian ia dihantar kepada sub-komponen, tetapi saya tidak tahu mengapa penyemak imbas terus melaporkan ralat yang mengatakan bahawa ini bukan nod dom. Minta petunjuk kepada Allah.
3. Cara umum untuk menulis peristiwa seret dan lepas adalah dengan mentakrifkan peristiwa pergerakan tetikus dan naik tetikus pada dokumen, tetapi kedua-dua peristiwa ini dikaitkan dengan parameter daripada dari , saya tidak dapat menjejaki parameter yang berkaitan. Jadi saya mentakrifkannya dari. Adakah terdapat cara yang lebih baik? Sila kongsi!
4. Revolusi masih belum berjaya, rakan-rakan masih perlu bekerja keras!
Demo ini telah dimuat naik ke: https://github.com/LuckyWinty/dragDemo
Di atas adalah keseluruhan kandungan artikel ini, saya harap ia akan membantu kajian semua orang.