摘要:不過(guò)在細(xì)說(shuō)之前我們先了解一下。這時(shí)候就是發(fā)揮作用的地方了。可以將一個(gè)對(duì)象轉(zhuǎn)化為對(duì)象。這四個(gè)屬性可以定位一段被選中的文字。如上圖,我們知道元素排列是一段一段的,這里的就是指的每個(gè)段,就是選中的位置??隙ㄊ沁B續(xù)的,這樣我們就可以定位一段完整的。
Range是JavaScript的內(nèi)置對(duì)象,一般來(lái)講用到的地方不是很多,主要是一些交互性比較強(qiáng)的場(chǎng)景可能會(huì)用到,比如高亮標(biāo)注,用不到還好說(shuō),如果用到了查資料確實(shí)也是比較少的, 所以這里總結(jié)一下筆記,不會(huì)太深入。
需要注意的是這里很多方法都屬于實(shí)驗(yàn)性功能, 所以生產(chǎn)環(huán)境使用的使用需要謹(jǐn)慎,具體可以參考MDN。這里不贅述了。
range的應(yīng)用場(chǎng)景這類相對(duì)比較生僻的api應(yīng)用常見(jiàn)并不是很多, 這里我們先了解一下range的應(yīng)用場(chǎng)景.
就是常見(jiàn)的高亮標(biāo)注電子書之類的
人工標(biāo)注機(jī)器學(xué)習(xí)所需的基礎(chǔ)文檔(我所做的)
當(dāng)然應(yīng)該也有很多其他場(chǎng)景, 我也沒(méi)怎么接觸. 有興趣的可以自行了解
Range是什么顧名思義,Range其實(shí)可以認(rèn)為是一個(gè)選中的文字范圍, 但是Range又不依賴于鼠標(biāo)選中, 我們可以自行構(gòu)造或者克隆。不過(guò)在細(xì)說(shuō)Range之前我們先了解一下Selection。
如圖當(dāng)我們選中一段文字時(shí), 我們就以通過(guò)window.getSelection來(lái)獲取Selection對(duì)象
Selection可以window.getSelection().toString()直接獲取選中的文字, 但是很多時(shí)候我們并不是要獲取選中的文字,而是要得到選中文字所在位置并將其存儲(chǔ)起來(lái)。這時(shí)候就是Range發(fā)揮作用的地方了。
window.getSelection().getRangeAt(0)可以將一個(gè)Selection對(duì)象轉(zhuǎn)化為Range對(duì)象。
我們需要關(guān)注的東西是startContainer,endContainer, startOffset,endOffset。這四個(gè)屬性可以定位一段被選中的文字。
如上圖,我們知道Dom元素排列是一段一段的, 這里的container就是指的每個(gè)段,offset就是選中的位置。Range肯定是連續(xù)的,這樣我們就可以定位一段完整的Range。
Range的存儲(chǔ)如果作為高亮, Range必然是要存到服務(wù)器上的, 但是作為js對(duì)象, Range不可以直接存到數(shù)據(jù)庫(kù)里,這時(shí)候就要對(duì)Range進(jìn)行一定的處理了。
上面提到過(guò)Range是可以手動(dòng)創(chuàng)建的:document.createRange:
var range = document.createRange(); range.setStart(startNode, startOffset); range.setEnd(endNode, endOffset);
這里startNode指startContainer, 自然就是指dom元素了,看到這里其實(shí)大家心里也該有點(diǎn)方案了,不好存儲(chǔ)的無(wú)非就是dom元素了,那我們將dom元素轉(zhuǎn)為選擇器存起來(lái)就好了, 到時(shí)再通過(guò)選擇器獲取dom元素。
當(dāng)然我們也有其他選擇: xpath, 主要是我接手項(xiàng)目的時(shí)候就是利用的xpath, 將dom轉(zhuǎn)為xpath的代碼如下:
// 獲取一個(gè)元素的xpath function getElementXPath (element) { if (!element) return null if (element.id) { return `//*[@id=${element.id}]` } else if (element.tagName === "BODY") { return "/html/body" } else { const sameTagSiblings = Array.from(element.parentNode.childNodes) .filter(e => e.nodeName === element.nodeName) const idx = sameTagSiblings.indexOf(element) return getElementXPath(element.parentNode) + "/" + element.tagName.toLowerCase() + (sameTagSiblings.length > 1 ? `[${idx + 1}]` : "") } }
將xpath轉(zhuǎn)化為Range:
function createRangeFromXPathRange (xpathRange) { var startContainer, endContainer, endOffset, evaluator = new XPathEvaluator() // must have legal start and end container nodes startContainer = evaluator.evaluate( xpathRange.startContainerPath, document.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ) if (!startContainer.singleNodeValue) { return null } if (xpathRange.collapsed || !xpathRange.endContainerPath) { endContainer = startContainer endOffset = xpathRange.startOffset } else { endContainer = evaluator.evaluate( xpathRange.endContainerPath, document.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ) if (!endContainer.singleNodeValue) { return null } endOffset = xpathRange.endOffset } // map to range object var range = document.createRange() range.setStart(startContainer.singleNodeValue, xpathRange.startOffset) range.setEnd(endContainer.singleNodeValue, endOffset) return range }總結(jié)
這篇文章筆記不會(huì)介紹太多api或者太過(guò)深入, 但是用法思路是一定的。共勉。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107907.html
摘要:其工作原理我已經(jīng)在第一篇做了大部分的闡述我尚未提及的是在創(chuàng)建新對(duì)象的時(shí)候,會(huì)賦予新對(duì)象一個(gè)屬性指向構(gòu)造器的屬性。 第四篇拖了很久了,真是有點(diǎn)不好意思。實(shí)話實(shí)說(shuō),拖延很久的原因主要是沒(méi)想好怎么寫,因?yàn)檫@一篇的主題比較有挑戰(zhàn)性:原型和基于原型的繼承——啊~我終于說(shuō)出口了,這下沒(méi)借口拖延了== 原型 我(個(gè)人)不喜歡的,就是講原型時(shí)上來(lái)就拿類做比較的,所以我不會(huì)這樣講。不過(guò)我的確講過(guò)構(gòu)造器函...
摘要:大多數(shù)情況下,對(duì)一個(gè)直接量和一個(gè)局部變量數(shù)據(jù)訪問(wèn)的性能差異是微不足道的。 前端性能優(yōu)化之 JavaScript 前言 本文為 《高性能 JavaScript》 讀書筆記,是利用中午休息時(shí)間、下班時(shí)間以及周末整理出來(lái)的,此書雖有點(diǎn)老舊,但談?wù)摰男阅軆?yōu)化話題是每位同學(xué)必須理解和掌握的,業(yè)務(wù)響應(yīng)速度直接影響用戶體驗(yàn)。 一、加載和運(yùn)行 大多數(shù)瀏覽器使用單進(jìn)程處理 UI 更新和 JavaScri...
摘要:使用要點(diǎn)同源限制分配給線程運(yùn)行的腳本文件,必須與主線程的腳本文件同源。限制線程所在的全局對(duì)象,與主線程不一樣,無(wú)法讀取主線程所在網(wǎng)頁(yè)的對(duì)象,也無(wú)法使用這些對(duì)象。通信聯(lián)系線程和主線程不在同一個(gè)上下文環(huán)境,它們不能直接通信,必須通過(guò)消息完成。 介紹 Web Worker為Web內(nèi)容在后臺(tái)線程中運(yùn)行腳本提供了一種簡(jiǎn)單的方法。線程可以執(zhí)行任務(wù)而不干擾用戶界面。此外,他們可以使用XMLHttpR...
摘要:線上另加入了排行榜功能,如需查看源碼的,請(qǐng)切換到分支整個(gè)項(xiàng)目結(jié)構(gòu)清晰,尤其單文件組件的表現(xiàn)力尤為突出,使得每個(gè)組件的邏輯都沒(méi)有過(guò)于復(fù)雜,而且在的統(tǒng)籌下,的單向數(shù)據(jù)流模式使得所有的變化都在可控制可預(yù)期的范圍內(nèi)。 2016注定不是個(gè)平凡年,無(wú)論是中秋節(jié)問(wèn)世的angular2,還是全面走向穩(wěn)定的React,都免不了面對(duì)另一個(gè)競(jìng)爭(zhēng)對(duì)手vue2。喜歡vue在設(shè)計(jì)思路上的先進(jìn)性(原諒我用了這么一個(gè)...
摘要:最近在自學(xué),無(wú)意看到群友一道比較有趣的問(wèn)題,故嘗試給出答案。目前給出的版本是最簡(jiǎn)單的情況,沒(méi)有考慮比較牌大小中出現(xiàn)數(shù)字或者字母重復(fù)的情況,以后有時(shí)間或許會(huì)給出更精細(xì)的版本。編寫程序,進(jìn)行撲克牌大小比較。 最近在自學(xué)Python,無(wú)意看到群友一道比較有趣的問(wèn)題,故嘗試給出答案。目前給出的版本是...
閱讀 1272·2021-11-23 09:51
閱讀 2662·2021-09-03 10:47
閱讀 2244·2019-08-30 15:53
閱讀 2429·2019-08-30 15:44
閱讀 1382·2019-08-30 15:44
閱讀 1205·2019-08-30 10:57
閱讀 1935·2019-08-29 12:25
閱讀 1098·2019-08-26 11:57