DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> JavaScript基礎知識 >> 再談React.js實現原生js拖拽效果
再談React.js實現原生js拖拽效果
編輯:JavaScript基礎知識     

前幾天寫的那個拖拽,自己留下的疑問。。。這次在熱心博友的提示下又修正了一些小小的bug,也加了拖拽的邊緣檢測部分。。。就再聊聊拖拽吧

一、不要直接操作dom元素

react中使用了虛擬dom的概念,目地就是要盡量避免直接操作dom元素,所以我們在對dom元素進行操作的時候需要注意,我之前為了獲取form的參數就直接用了var dragBox=document.getElementById('form')去找dom,但是其實記錄from的初始位置,可以在其子組件更新父組件參數的時候調用。即在MyFrom組件中獲取,如下代碼:

onChildChanged:function(newState){
    /*以下為修改處*/
    var computedStyle=document.defaultView.getComputedStyle(ReactDOM.findDOMNode(this.refs.dragBox),null);
    newState.left=computedStyle.left;
    newState.top=computedStyle.top;
    /*以上為修改處*/
    this.setState(newState);
},

這樣就可以直接在父組件中操作自己,而不是在子組件中調用。

二、onmousemove和onmouseup事件應該綁定到document上

拖拽事件中,當鼠標在DragArea中按下後,就應該檢測鼠標在document中移動的距離及何時彈起。否則直接綁定在form的話會有一個不雅的地方,就是拖動條拖動邊緣附近的時候,如果鼠標速度快一點會失效,鼠標再回來拖動條會自動吸上鼠標。因此利用react初始化階段的componentDidMount函數,這個函數是組件被裝載後才會被調用,也就是說調用這個方法的時候,組件已經被渲染到了頁面上,這個時候可以修改DOM。也就是說此時把相應事件再綁定到document上面,如下代碼:

componentDidMount:function(){
  document.addEventListener('mousemove',(e)=>{this.move(e);},false);/*ES6新特性,箭頭函數,需要依賴jsx編譯工具才能正確運行*/
  document.addEventListener('mouseup',(e)=>{this.endDrag(e);},false);
},

這樣就可以消除那個小小的bug啦!

三、增加邊緣檢測

一般情況下的拖拽,我們都是不希望能夠拖出可視窗口之外的,因此這就需要檢測。檢測四個方向上的位置,即上、下、左、右。顯然,上的距離top和左邊left的距離必須要大於等於0,下邊和右的距離必須要小於視口大小減去from本身的元素寬高。

具體代碼:

move:function(event){
    var e = event ? event : window.event;
    var dBox=ReactDOM.findDOMNode(this.refs.dragBox);
    if (this.state.flag) {
        var nowX = e.clientX, nowY = e.clientY;
        var disX = nowX - this.state.currentX, disY = nowY - this.state.currentY;
        /*增加拖拽范圍檢測*/
        var currentLeft=parseInt(this.state.left) + disX;
        var currentTop=parseInt(this.state.top) + disY;
        var docX=document.documentElement.clientWidth||document.body.clientWidth;
        var docY=document.documentElement.clientHeight||document.body.clientHeight;
        if(currentLeft<=250){//檢測屏幕左邊,因為我這裡的初始居中是利用了負1/2的盒子寬度的margin,所以用250px判斷邊界
            dBox.style.left=250+"px";
        }else if(currentLeft>=(docX-dBox.offsetWidth+250)){ //檢測右邊
            dBox.style.left=(docX-this.state.offsetX)+"px";
        }else{
            dBox.style.left =currentLeft+ "px";
        }
        if(currentTop<=200){ //檢測屏幕上邊,因為我這裡的初始居中是利用了負1/2的盒子高度的margin,所以用200px判斷邊界 
dBox.style.top=200+"px";
}else if(currentTop>=(docY-dBox.offsetHeight+200)){ //檢測下邊
dBox.style.top=(docY-this.state.offsetY)+"px";
}else{
dBox.style.top = currentTop + "px";
}
}

 

PS:新的代碼已經更新在我的github上面,大家可以研究一下。

 本文實質上為《React.js實現原生js拖拽及思考》的續篇,看不懂的話可以先看一下。

 

持續學習中。。。。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved