亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

基于React.js實現原生js拖拽效果引發的思考

2019-11-20 10:19:45
字體:
來源:轉載
供稿:網友

一、起因&思路

一直想寫一個原生js拖拽效果,又加上近來學react學得比較嗨。所以就用react來實現這個拖拽效果。

首先,其實拖拽效果的思路是很簡單的。主要就是三個步驟:

1.onmousedown的時候,啟動可拖拽事件,記錄被拖拽元素的原始坐標參數。

2.onmousemove的時候,實時記錄鼠標移動的距離,結合被拖拽元素第一階段的坐標參數,計算并設置新的坐標值。

3.onmouseup的時候,關閉可拖拽事件,記錄新的坐標值。

注意:這里主要是通過絕對定位的top和left來確定元素的位置的,因此被拖拽元素的css一定要設置絕對定位。

二、輔助工具

輔助工具主要就是是開發過程變得高效,而且酷炫的。在這個demo中,要給大家推薦一個gulp+browser-sync的開發工具,gulp有很多功能,在這個demo中gulp的作用主要是可以設置實時編譯react中的jsx文件,當然如果你寫css用的是sass,也可以設置實時編譯sass。用browser-sync這個呢,主要就是可以自動實時刷新頁面,我們平時做頁面,看效果的時候,通常都是通過F5來刷新瀏覽器,然后看到頁面的。但是用了這個插件,你寫完代碼的時候,只要按下,ctrl+s保存,新的效果就會自動在瀏覽器中刷新,然后看得到了。

用法詳解:

安裝:

1.在node的環境下,安裝gulp,這里就不詳說了,具體過程可參考我的博文《react.js入門必須知道的那些事》

2.安裝gulp-livereload,在命令行或者git bash ,輸入npm install --save-dev gulp-livereload

3.安裝gulp-watch,在命令行或者git bash ,輸入npm install --save-dev gulp-watch

4.安裝browser-sync,在命令行或者git bash ,輸入npm install --save-dev browser-sync

配置及解釋如圖:

三、定義組件構建頁面

備注:這里的代碼說明均在react相關模塊安裝好的情況下,安裝過程見我的博文《react.js入門必須知道的那些事》.

效果圖:

組件拆分思路:

我當時覺得組件拆分得細一點好,所以我把input、button分別做成了一個組件:

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;

由于input有很多都是需要指定的,這種情況下,如果像我這樣定義需要傳太多參數,而且其實登陸的input大多都是固定且沒必要復用的,所以這樣其實不大好。這里的input直接寫比較好。

寫好之后的父組件:

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>  );

備注:因為demo中需要獲取真實的dom節點,所以定義了ref。

再加上css樣式,頁面就完成啦!最后,重點來啦?。?!

四、父子組件間通信實現拖拽

說明:由于我要實現的效果是,鼠標按住子組件DragArea的時候,拖動的是整個form,所以啟動拖拽的是DragArea,而響應的是form。所以,一開始必須把父組件的一些狀態屬性傳給子組件,然后鼠標在DragArea按下的的時候,必須通過子組件DragArea找到父組件的原始坐標參數,然后更新父組件里面的狀態屬性,并且告訴父組件可以進行拖拽了。父組件給子組件傳參就是直接傳遞的。而子組件給父組件傳參需要通過事件。所以在父組件中定義這么一個函數:

onChildChanged:function(newState){ //因為參數過多,所以把參數放到對象里面,通過對象來傳  this.setState(newState);},

而子組件需要綁定這個函數,如上面的代碼:callbackParent={this.onChildChanged}

在子組件中,響應的函數為:

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>}

 這樣,在子組件中就啟動了拖拽開關,并且已經更新了from的相關參數,from的兩外兩個事件,move和endDrag分別為:

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  });}

至此,拖拽實現!

五、反思回顧

 1.理論上來說,拖拽效果可以在任意元素中實現,拖拽的思路都是一致的,所以理論上來說,拖拽各個過程的函數可以抽離出來,做成一個Mixin,然后可以反復調用。我一開始的思路就是這樣,但是在傳參、響應、綁定元素上面總是出錯。查找了一下資料,沒找到react與拖拽的簡單寫法資料,只有一些react的專用插件,而且是用ES6的寫法,由于現在的水平還沒能看懂。所以暫時放棄了這種寫法。希望有相關想法的大神們和我交流一下。

2.文中子組件獲取from的參數時,用了var dragBox=document.getElementById('form');去找dom,這樣好像違反了react的一些理念。但是我還不是很熟悉該怎么從子組件獲取父組件的dom。我試過在父組件定義refs=this.refs.dragBox。然后傳給子組件,但是不知道為什么瀏覽器一直報錯說這個不是dom節點。求大神指教。

3.拖拽事件的一般寫法,是在document上面定義mousemove和mouseup事件,但是這兩個事件都關聯到from的參數,這樣的話,如果我在react中定義在document,就跟蹤不了相關參數。所以我就定義在了from上面。是不是有更好的方法呢?求分享!

4.革命尚未成功,同志仍需努力!

 本demo已上傳至:https://github.com/LuckyWinty/dragDemo

以上就是本文的全部內容,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩视频在线免费观看| 国产亚洲一区二区精品| 久久久最新网址| 国产激情999| 成人国产精品色哟哟| 成人在线小视频| 久久在线精品视频| 日日狠狠久久偷偷四色综合免费| 亚洲美女激情视频| 亚洲福利在线看| 亚洲视频在线观看| 黑人欧美xxxx| 国产成人久久精品| 亚洲精品欧美日韩专区| 久久露脸国产精品| 国产97色在线|日韩| 欧美最顶级丰满的aⅴ艳星| 在线观看日韩专区| 这里只有精品在线播放| 国产精品久久91| 午夜精品久久久久久99热软件| 欧美成人精品在线| 亚洲欧洲日产国产网站| 国产精品18久久久久久麻辣| 国内久久久精品| 成人国产精品一区| 原创国产精品91| 日韩精品一区二区视频| 久久久精品美女| 成人激情视频在线观看| 日韩电影第一页| 欧美激情亚洲一区| 亚洲第一色中文字幕| 国产91色在线播放| 亚洲天堂av在线播放| 久久久国产一区二区| 色视频www在线播放国产成人| 国产欧美亚洲精品| 国产日韩av高清| 91精品国产免费久久久久久| 久久精品国产综合| 日韩在线免费视频观看| 国内外成人免费激情在线视频网站| 欧美黄色性视频| 亚洲自拍另类欧美丝袜| 26uuu另类亚洲欧美日本老年| 色综合导航网站| 国产精品一区二区三区在线播放| 中文字幕亚洲综合| 国产综合色香蕉精品| 国产一区二区黑人欧美xxxx| 2019国产精品自在线拍国产不卡| 亚洲国产99精品国自产| 日韩乱码在线视频| 国产欧美一区二区三区在线看| 日本一区二区在线免费播放| 精品国产成人av| 成人黄色av网站| 亚洲精品在线观看www| 精品日本美女福利在线观看| 中文字幕在线观看亚洲| 免费av在线一区| 国产一区欧美二区三区| 国产香蕉一区二区三区在线视频| 亚洲a级在线播放观看| 国产欧美一区二区| 久久夜色精品国产欧美乱| 69av视频在线播放| 亚洲在线www| 精品色蜜蜜精品视频在线观看| 国产在线不卡精品| 91美女高潮出水| 国产精品一区久久久| 国产成人精品一区二区| 欧美精品免费在线观看| 在线成人一区二区| 欧美性精品220| 中文字幕日韩精品在线| 中日韩午夜理伦电影免费| 成人乱色短篇合集| 久久频这里精品99香蕉| 中文字幕亚洲二区| 精品五月天久久| 91免费国产视频| 91亚洲国产成人精品性色| 伊人久久久久久久久久| 亚洲天堂久久av| 国产精品白丝jk喷水视频一区| 欧美精品www在线观看| 日韩欧美成人区| 国产日韩欧美视频在线| 欧美国产日韩一区二区| 亚洲精品自产拍| 国产成人极品视频| 欧美亚洲国产精品| 国产欧美一区二区三区在线看| 亚洲视频自拍偷拍| 亚洲第一二三四五区| 成人性生交大片免费看小说| 欧美性xxxx18| 欧美日韩午夜激情| 国产在线拍偷自揄拍精品| 中文字幕av一区二区三区谷原希美| 成人在线免费观看视视频| 亚洲男人天堂2023| 日韩av手机在线| 在线观看日韩www视频免费| 最近中文字幕2019免费| 78色国产精品| 欧美福利视频在线| 国产精品久久久久aaaa九色| 国产精品久久久久久久久久小说| 97国产真实伦对白精彩视频8| 81精品国产乱码久久久久久| 欧美亚洲第一页| 国产精品人人做人人爽| 日本19禁啪啪免费观看www| 欧美丝袜一区二区三区| 性色av一区二区三区在线观看| 亚洲a成v人在线观看| 亚洲国产欧美日韩精品| 色综合91久久精品中文字幕| 日韩在线精品视频| 青青草原成人在线视频| 亚洲精品小视频在线观看| 欧美日韩福利视频| 日韩精品中文字幕在线| 久久久亚洲天堂| 色婷婷综合成人av| 精品国产美女在线| 奇米4444一区二区三区| 国产91网红主播在线观看| 九九热99久久久国产盗摄| 日韩欧美极品在线观看| 曰本色欧美视频在线| 成人性教育视频在线观看| 日韩在线欧美在线| 一区二区福利视频| 91精品久久久久| 日韩av在线影视| 91久久精品国产91久久| 久久精品亚洲国产| 欧洲成人在线视频| 成人a免费视频| 欧美大胆a视频| 久久精品国产亚洲精品2020| 欧美高清视频免费观看| 久久综合伊人77777| 国产精品露脸自拍| 久久精品国产成人| 日本19禁啪啪免费观看www| 国产精品99蜜臀久久不卡二区| 2019国产精品自在线拍国产不卡| 国产亚洲精品久久久久久| 日本久久91av| 日本久久久久亚洲中字幕| 日韩中文综合网| 成人午夜两性视频| 欧美孕妇与黑人孕交| 国产精品福利无圣光在线一区| 国产热re99久久6国产精品| 久久久久久欧美| 高清在线视频日韩欧美| 亚洲福利在线看|