首頁 web前端 js教程 再一次談論React.js實作原生js拖曳效果所引起的一系列問題_javascript技巧

再一次談論React.js實作原生js拖曳效果所引起的一系列問題_javascript技巧

May 16, 2016 pm 03:06 PM

React 起源於 Facebook 的內部項目,因為該公司對市場上所有 JavaScript MVC 框架,都不滿意,就決定自己寫一套,用來架設 Instagram 的網站。做出來以後,發現這套東西很好用,就在2013年5月就開源了。由於 React 的設計想法極為獨特,屬於革命性創新,因此性能出眾,但程式碼邏輯卻非常簡單。所以,越來越多人開始關注和使用,認為它可能是未來的 Web 開發的主流工具。

前幾天寫的那個拖拽,自己留下的疑問。 。 。這次在熱心博友的提示下又修正了一些小小的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判断边界 <br> dBox.style.top=200+"px"; <br> }else if(currentTop>=(docY-dBox.offsetHeight+200)){ //检测下边<br> dBox.style.top=(docY-this.state.offsetY)+"px";<br> }else{<br> dBox.style.top = currentTop + "px"; <br> }<br> }
登入後複製

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

ReactJS的背景與原理

在Web開發中,我們總是需要將變化的資料即時反應到UI上,這時就需要對DOM進行操作。而複雜或頻繁的DOM操作通常是效能瓶頸產生的原因(如何進行高效能的複雜DOM操作通常是衡量一個前端開發人員技能的重要指標)。 React為此引進了虛擬DOM(Virtual DOM)的機制:在瀏覽器端用Javascript實作了一套DOM API。基於React進行開發時所有的DOM構造都是透過虛擬DOM進行,每當資料變化時,React都會重新建構整個DOM樹,然後React將目前整個DOM樹和上一次的DOM樹進行對比,得到DOM結構的區別,然後僅將需要變化的部分進行實際的瀏覽器DOM更新。而React能夠批次虛擬DOM的刷新,在一個事件循環(Event Loop)內的兩次資料變化會被合併,例如你連續的先將節點內容從A變成B,然後又從B變成A, React會認為UI不會發生任何變化,而如果透過手動控制,這種邏輯通常是極其複雜的。儘管每一次都需要建構完整的虛擬DOM樹,但是因為虛擬DOM是內存數據,性能是極高的,而對實際DOM進行操作的僅僅是Diff部分,因而能達到提高性能的目的。這樣,在確保效能的同時,開發者將不再需要關注某個資料的變化如何更新到一個或多個特定的DOM元素,而只需要關心在任意一個資料狀態下,整個介面是如何Render的。

如果你像在90年代那樣寫過伺服器端Render的純Web頁面那麼應該知道,伺服器端要做的就是根據資料Render出HTML送到瀏覽器端。如果這時因為使用者的一個點擊需要改變某個狀態文字,那麼也是透過刷新整個頁面來完成的。伺服器端並不需要知道是哪一小段HTML發生了變化,而只需要根據資料刷新整個頁面。換句話說,任何UI的變化都是透過整體刷新來完成的。而React將這種開發模式以高效能的方式帶到了前端,每做一點介面的更新,你都可以認為刷新了整個頁面。至於如何進行局部更新以確保效能,則是React框架要完成的事情。

借用Facebook介紹React的視訊中聊天應用程式的例子,當一條新的訊息過來時,傳統開發的思路如上圖,你的開發過程需要知道哪條數據過來了,如何將新的DOM結點添加到目前DOM樹上;而基於React的開發想法如下圖,你永遠只需要關心資料整體,兩次資料之間的UI如何變化,則完全交給框架去做。可以看到,使用React大大降低了邏輯複雜性,這意味著開發難度降低,可能產生Bug的機會也更少。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

在JavaScript中替換字符串字符 在JavaScript中替換字符串字符 Mar 11, 2025 am 12:07 AM

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

構建您自己的Ajax Web應用程序 構建您自己的Ajax Web應用程序 Mar 09, 2025 am 12:11 AM

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

如何創建和發布自己的JavaScript庫? 如何創建和發布自己的JavaScript庫? Mar 18, 2025 pm 03:12 PM

文章討論了創建,發布和維護JavaScript庫,專注於計劃,開發,測試,文檔和促銷策略。

如何在瀏覽器中優化JavaScript代碼以進行性能? 如何在瀏覽器中優化JavaScript代碼以進行性能? Mar 18, 2025 pm 03:14 PM

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

jQuery矩陣效果 jQuery矩陣效果 Mar 10, 2025 am 12:52 AM

將矩陣電影特效帶入你的網頁!這是一個基於著名電影《黑客帝國》的酷炫jQuery插件。該插件模擬了電影中經典的綠色字符特效,只需選擇一張圖片,插件就會將其轉換為充滿數字字符的矩陣風格畫面。快來試試吧,非常有趣! 工作原理 插件將圖片加載到畫布上,讀取像素和顏色值: data = ctx.getImageData(x, y, settings.grainSize, settings.grainSize).data 插件巧妙地讀取圖片的矩形區域,並利用jQuery計算每個區域的平均顏色。然後,使用

如何使用瀏覽器開發人員工具有效調試JavaScript代碼? 如何使用瀏覽器開發人員工具有效調試JavaScript代碼? Mar 18, 2025 pm 03:16 PM

本文討論了使用瀏覽器開發人員工具的有效JavaScript調試,專注於設置斷點,使用控制台和分析性能。

如何構建簡單的jQuery滑塊 如何構建簡單的jQuery滑塊 Mar 11, 2025 am 12:19 AM

本文將引導您使用jQuery庫創建一個簡單的圖片輪播。我們將使用bxSlider庫,它基於jQuery構建,並提供許多配置選項來設置輪播。 如今,圖片輪播已成為網站必備功能——一圖胜千言! 決定使用圖片輪播後,下一個問題是如何創建它。首先,您需要收集高質量、高分辨率的圖片。 接下來,您需要使用HTML和一些JavaScript代碼來創建圖片輪播。網絡上有很多庫可以幫助您以不同的方式創建輪播。我們將使用開源的bxSlider庫。 bxSlider庫支持響應式設計,因此使用此庫構建的輪播可以適應任何

如何使用Angular上傳和下載CSV文件 如何使用Angular上傳和下載CSV文件 Mar 10, 2025 am 01:01 AM

數據集對於構建API模型和各種業務流程至關重要。這就是為什麼導入和導出CSV是經常需要的功能。在本教程中,您將學習如何在Angular中下載和導入CSV文件

See all articles