成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript之Range--或許會(huì)有點(diǎn)用

stonezhu / 1097人閱讀

摘要:不過(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

相關(guān)文章

  • 理解 JavaScript(四)

    摘要:其工作原理我已經(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)造器函...

    cuieney 評(píng)論0 收藏0
  • 前端性能優(yōu)化 JavaScript

    摘要:大多數(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...

    Coding01 評(píng)論0 收藏0
  • JavaScriptWeb Worker

    摘要:使用要點(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...

    BigNerdCoding 評(píng)論0 收藏0
  • 單文件組件下的vue,可以擦出怎樣的火花

    摘要:線上另加入了排行榜功能,如需查看源碼的,請(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è)...

    Keven 評(píng)論0 收藏0
  • 趣味Python題目10月8日

    摘要:最近在自學(xué),無(wú)意看到群友一道比較有趣的問(wèn)題,故嘗試給出答案。目前給出的版本是最簡(jiǎn)單的情況,沒(méi)有考慮比較牌大小中出現(xiàn)數(shù)字或者字母重復(fù)的情況,以后有時(shí)間或許會(huì)給出更精細(xì)的版本。編寫程序,進(jìn)行撲克牌大小比較。 最近在自學(xué)Python,無(wú)意看到群友一道比較有趣的問(wèn)題,故嘗試給出答案。目前給出的版本是...

    Mertens 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<