最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解如何使用JavaScript獲取自動(dòng)消失的聯(lián)想詞

 更新時(shí)間:2024年06月11日 11:48:10   作者:洛小豆  
前幾天在做數(shù)據(jù)分析時(shí),我嘗試獲取某網(wǎng)站上輸入搜索詞后的聯(lián)想詞,輸入搜索詞后會(huì)彈出一個(gè)顯示聯(lián)想詞的框,有趣的是,輸入框失去焦點(diǎn)后,聯(lián)想詞彈框就自動(dòng)消失了,這種情況下該怎么辦呢,所以本文給大家介紹了如何使用JavaScript獲取自動(dòng)消失的聯(lián)想詞,需要的朋友可以參考下

我問(wèn)題

前幾天在做數(shù)據(jù)分析時(shí),我嘗試獲取某網(wǎng)站上輸入搜索詞后的聯(lián)想詞,輸入搜索詞后會(huì)彈出一個(gè)顯示聯(lián)想詞的框。有趣的是,當(dāng)我嘗試通過(guò)按F12定位這個(gè)彈框在HTML中的位置時(shí),輸入框失去焦點(diǎn)后,聯(lián)想詞彈框就自動(dòng)消失了。我觀察到 HTML 代碼中div元素也從代碼中消失了。這種情況下,我該如何才能準(zhǔn)確地定位這個(gè)元素彈框并獲取其中的聯(lián)想詞呢?

動(dòng)畫.gif

解決方案

方法一:查找DOM節(jié)點(diǎn)

這算是最簡(jiǎn)單的操作,通過(guò)調(diào)試框可以看到網(wǎng)頁(yè)dom結(jié)構(gòu)的變化,當(dāng)觸發(fā)聯(lián)想詞彈框時(shí),記下彈框?qū)?yīng)標(biāo)簽的類名或者id,然后查找得到這個(gè)標(biāo)簽的html代碼,從中解析出聯(lián)想詞。

const elementByClassName = document.querySelector(".luoxiaodou");
if (elementByClassName) {
    const htmlContent = elementByClassName.innerHTML;
    console.log(htmlContent);
}

輸入框獲取焦點(diǎn)時(shí),聯(lián)想詞彈框出現(xiàn),輸入框失去焦點(diǎn)時(shí),聯(lián)想詞彈框消失。咱們先給輸入框添加焦點(diǎn),彈框出現(xiàn)時(shí),運(yùn)行上面的代碼獲取節(jié)點(diǎn)對(duì)應(yīng)的html內(nèi)容。

這個(gè)想法很好,但是這里有一個(gè)問(wèn)題:就是元素的加載需要時(shí)間,需要請(qǐng)求服務(wù)端獲取數(shù)據(jù),然后再加載出來(lái)。,如果是輸入框獲取焦點(diǎn)后立即去查找元素,大概率獲取的結(jié)果是空,所以這中間要有延遲的時(shí)間,咱們就說(shuō)這坑大家有沒(méi)有踩過(guò)吧。

方法二:使用MutationObserver來(lái)監(jiān)視DOM變化

我還有兩個(gè)想法,第一個(gè)是:咱們能不能攔截一下網(wǎng)絡(luò),然后從服務(wù)器的響應(yīng)里頭撈點(diǎn)聯(lián)想詞出來(lái)?我個(gè)人覺(jué)得這招兒挺靠譜的,但目前還沒(méi)來(lái)得及試試。等我嘗試之后寫一下關(guān)于監(jiān)聽(tīng)網(wǎng)絡(luò)請(qǐng)求獲取聯(lián)想詞的內(nèi)容,咱們就先記個(gè)賬,到時(shí)候一定補(bǔ)上。

另一種方式就是使用MutationObserver來(lái)監(jiān)視DOM變化,可以在控制臺(tái)中編寫一個(gè)JavaScript函數(shù),當(dāng)包含特定類的元素出現(xiàn)在DOM中時(shí),打印出該元素的HTML內(nèi)容。為此,你可以使用MutationObserver來(lái)監(jiān)視DOM變化。

而我選擇了另一種可能的解決方案,就是利用MutationObserver這個(gè)JavaScript API。一旦檢測(cè)到DOM中有特定類的元素出現(xiàn),就立即打印出它的HTML內(nèi)容。MutationObserver 是 JavaScript 自帶的 API,它用于監(jiān)視DOM樹(shù)的變化。這是瀏覽器原生支持的功能,包括我們常用的Chrome在內(nèi)。正好在插件開(kāi)發(fā)中使用。

咱們可以創(chuàng)建一個(gè)函數(shù),傳參是標(biāo)簽選擇器和一個(gè)回調(diào)函數(shù),當(dāng)獲取到變化的網(wǎng)頁(yè)時(shí),調(diào)用回調(diào)函數(shù)解析獲取聯(lián)想詞。這里使用一個(gè)map集合,可以保證管理多個(gè)監(jiān)視器,以下是實(shí)現(xiàn)代碼:

const observers = new Map()

/**
 * 啟動(dòng)監(jiān)視指定選擇器的元素變化。
 * @param {string} selector - CSS選擇器,可以是類名(以`.`開(kāi)頭)或ID(以`#`開(kāi)頭)。
 * @param {function} callback - 回調(diào)函數(shù),當(dāng)符合選擇器的元素添加到DOM時(shí)調(diào)用。
 */
function startObserving(selector, callback) {
  /**
   * 觀察者回調(diào)函數(shù),監(jiān)視DOM樹(shù)的變化。
   * @param {MutationRecord[]} mutationsList - DOM變化記錄的列表。
   * @param {MutationObserver} observer - 觀察者實(shí)例。
   */
  const observerCallback = function (mutationsList, observer) {
    for (const mutation of mutationsList) {
      if (mutation.type === 'childList') {
        mutation.addedNodes.forEach((node) => {
          if (node.nodeType === Node.ELEMENT_NODE) {
            if (selector.startsWith('#') && node.id === selector.slice(1)) {
              callback(node.outerHTML)
            } else if (selector.startsWith('.') && node.classList.contains(selector.slice(1))) {
              callback(node.outerHTML)
            }
          }
        })
      }
    }
  }
  // 創(chuàng)建一個(gè)觀察者實(shí)例并開(kāi)始觀察指定的目標(biāo)節(jié)點(diǎn)和配置
  const observer = new MutationObserver(observerCallback)
  // 觀察配置,配置對(duì)象指定我們希望觀察子節(jié)點(diǎn)的變化(`childList: true`)以及觀察整個(gè)子樹(shù)中的變化(`subtree: true`)
  const config = { childList: true, subtree: true }
  // 觀察整個(gè)文檔,所以將目標(biāo)節(jié)點(diǎn)設(shè)置為`document.body`。
  observer.observe(document.body, config)
  // 將觀察者存儲(chǔ)在Map中
  observers.set(selector, observer)

  // 設(shè)置定時(shí)器,指定時(shí)間后自動(dòng)停止觀察并刪除觀察者,回收資源
  setTimeout(() => {
    stopObserving(selector)
  }, 5 * 60 * 1000)
}


/**
 * 停止監(jiān)視指定選擇器的元素變化。
 * @param {string} selector - CSS選擇器,可以是類名(以`.`開(kāi)頭)或ID(以`#`開(kāi)頭)。
 */
function stopObserving(selector) {
    const observer = observers.get(selector);

    if (observer) {
        observer.disconnect();
        observers.delete(selector);
    }
}

export { startObserving, stopObserving };

然后就是在使用的地方,導(dǎo)入這些方法,傳一下參數(shù)就可以了,有一點(diǎn)要注意:回調(diào)函數(shù)中的參數(shù)是獲取到的網(wǎng)頁(yè)信息

import { startObserving, stopObserving } from './element-observer.js';

// 通過(guò)類名啟動(dòng)監(jiān)視
startObserving('.xiaodou-class', (htmlContent) => {
    console.log('Element with class added:', htmlContent);
});

// 通過(guò)ID啟動(dòng)監(jiān)視
startObserving('#xiaodou-id', (htmlContent) => {
    console.log('Element with ID added:', htmlContent);
});

// 停止監(jiān)視
setTimeout(() => {
    stopObserving('.xiaodou-class');
    stopObserving('#xiaodou-id');
}, 6000);

你是不是以為這就結(jié)束?我當(dāng)時(shí)就是這么想的,但是還是有問(wèn)題:從第二次開(kāi)始獲取到的內(nèi)容是上一個(gè)輸入詞的聯(lián)想詞。假設(shè)第一次輸入“貓咪”,然后獲取的“貓咪”的聯(lián)想詞,第二次輸入“狗狗”,但是獲取的還是“貓咪”的聯(lián)想詞,第三次輸入“兔兔”,這次獲取的是“狗狗”的聯(lián)想詞,這是哪里出問(wèn)題了呢?

接著咱們來(lái)分析一下原因,首先觀察一下聯(lián)想詞彈框的變化,比如下圖,修改”貓咪貍花貓“到”貓咪貍“的這個(gè)過(guò)程中,聯(lián)想詞彈框先出來(lái)跟”貓咪貍花貓“相關(guān)的內(nèi)容, 再請(qǐng)求服務(wù)器獲取”貓咪貍“的聯(lián)想詞,再更新彈框內(nèi)容。

動(dòng)畫.gif

當(dāng)頁(yè)面變動(dòng)時(shí),監(jiān)控頁(yè)面變化的函數(shù)會(huì)立即執(zhí)行,這個(gè)執(zhí)行速度是優(yōu)于請(qǐng)求服務(wù)器更新彈框內(nèi)容的速度,所以這里導(dǎo)致獲取的內(nèi)容是是上一個(gè)聯(lián)想詞的。

發(fā)現(xiàn)了問(wèn)題,就好修改了,可以嘗試在 MutationObserver 回調(diào)函數(shù)中使用 setTimeout,以確保 DOM 完全渲染后再獲取 outerHTML。

/**
* 觀察者回調(diào)函數(shù),監(jiān)視DOM樹(shù)的變化。
* @param {MutationRecord[]} mutationsList - DOM變化記錄的列表。
* @param {MutationObserver} observer - 觀察者實(shí)例。
*/
const observerCallback = function (mutationsList, observer) {
for (const mutation of mutationsList) {
  if (mutation.type === 'childList') {
    mutation.addedNodes.forEach((node) => {
      if (node.nodeType === Node.ELEMENT_NODE) {
        if (selector.startsWith('#') && node.id === selector.slice(1)) {
          // 使用 setTimeout 確保 DOM 完全渲染后獲取 outerHTML
          setTimeout(() => callback(node.outerHTML), 1000);
        } else if (selector.startsWith('.') && node.classList.contains(selector.slice(1))) {
          // 使用 setTimeout 確保 DOM 完全渲染后獲取 outerHTML
          setTimeout(() => callback(node.outerHTML), 1000);
        }
      }
    });
  }
}

這里確實(shí)解決了問(wèn)題,但是我還有一個(gè)疑問(wèn):為什么在修改”貓咪貍花貓“到”貓咪貍“的這個(gè)過(guò)程中,彈框內(nèi)容有兩次變化,觀察者只觸發(fā)了一次?,在上面的觀察者配置是希望觀察子節(jié)點(diǎn)的變化以及觀察整個(gè)子樹(shù)中的變化,這個(gè)變化不包含節(jié)點(diǎn)內(nèi)容的變化,不知道這樣理解對(duì)不對(duì)?

以上就是詳解如何使用JavaScript獲取自動(dòng)消失的聯(lián)想詞的詳細(xì)內(nèi)容,更多關(guān)于JavaScript獲取聯(lián)想詞的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • element-table表格中插入顏色塊顯示數(shù)據(jù)狀態(tài)的示例代碼

    element-table表格中插入顏色塊顯示數(shù)據(jù)狀態(tài)的示例代碼

    這篇文章主要介紹了element-table表格中插入顏色塊顯示數(shù)據(jù)狀態(tài),代碼部分分為dom部分和data部分及css部分,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-12-12
  • JavaScript中的Promise詳解

    JavaScript中的Promise詳解

    現(xiàn)在網(wǎng)上有非常多的Promise文章,但都是給你一堆代碼,或者某些核心代碼,讓你看完之后感覺(jué),嗯,很厲害,但還是不知所云,不知其所以然。那么本文真正從一個(gè)小白開(kāi)始帶你深入淺出,一步一步實(shí)現(xiàn)自己的 Promise,這種自己造輪子的過(guò)程一定是進(jìn)步最快的過(guò)程,快上車開(kāi)始吧
    2022-11-11
  • js判斷變量初始化的三種形式及推薦用的形式

    js判斷變量初始化的三種形式及推薦用的形式

    這篇文章主要介紹了js判斷變量初始化的三種形式及推薦用的形式,需要的朋友可以參考下
    2014-07-07
  • 使用 JavaScript 進(jìn)行函數(shù)式編程 (一) 翻譯

    使用 JavaScript 進(jìn)行函數(shù)式編程 (一) 翻譯

    本文是函數(shù)式編程系列的第一篇文章。這里我會(huì)簡(jiǎn)要介紹一下編程范式,然后會(huì)直接介紹使用 Javascript 進(jìn)行函數(shù)式編程的概念,因?yàn)?JavsScript 是最被認(rèn)可的函數(shù)式程序語(yǔ)言之一。我們鼓勵(lì)讀者通過(guò)參考資料部分進(jìn)一步了解這一迷人的概念
    2015-10-10
  • 最新熱門腳本Autojs源碼分享

    最新熱門腳本Autojs源碼分享

    AutoJS 是基于一個(gè)標(biāo)準(zhǔn)字典庫(kù)的文本輸入自動(dòng)完成 JavaScript 庫(kù)。Auto.js 是使用純 JS 實(shí)現(xiàn)的,沒(méi)有任務(wù)外部依賴,大小僅僅 6kb,本文給大家分享最新熱門腳本Autojs源碼,感興趣的朋友一起看看吧
    2021-05-05
  • uniapp通過(guò)概率實(shí)現(xiàn)隨機(jī)抽獎(jiǎng)的項(xiàng)目實(shí)踐

    uniapp通過(guò)概率實(shí)現(xiàn)隨機(jī)抽獎(jiǎng)的項(xiàng)目實(shí)踐

    在很多電商平臺(tái)或者活動(dòng)中,都會(huì)有類似抽獎(jiǎng)贏優(yōu)惠券的功能,本文主要介紹了uniapp通過(guò)概率實(shí)現(xiàn)隨機(jī)抽獎(jiǎng)的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-04-04
  • 用svg制作富有動(dòng)態(tài)的tooltip

    用svg制作富有動(dòng)態(tài)的tooltip

    這篇文章主要介紹了用svg制作富有動(dòng)態(tài)的tooltip的代碼以及制作過(guò)程,十分的細(xì)致全面,有需要的小伙伴可以參考下。
    2015-07-07
  • 原生JS中slice()方法和splice()區(qū)別

    原生JS中slice()方法和splice()區(qū)別

    slice()方法和splice()方法都是原生js中對(duì)數(shù)組操作的方法。那么他兩種有什么區(qū)別呢?今天通過(guò)本文教程給大家簡(jiǎn)單介紹下,需要的朋友可以參考下
    2017-03-03
  • 基于Bootstrap實(shí)現(xiàn)的下拉菜單手機(jī)端不能選擇菜單項(xiàng)的原因附解決辦法

    基于Bootstrap實(shí)現(xiàn)的下拉菜單手機(jī)端不能選擇菜單項(xiàng)的原因附解決辦法

    小編使用bootstrap做的下拉菜單在電腦瀏覽器中可以正常使用,在手機(jī)瀏覽器中能彈出下拉列表卻不能選擇列表中的菜單項(xiàng),怎么回事,如何解決呢?下面小編給大家分享下具體原因及解決辦法,一起看下吧
    2016-07-07
  • JSONP原理及應(yīng)用實(shí)例詳解

    JSONP原理及應(yīng)用實(shí)例詳解

    這篇文章主要介紹了JSONP原理及應(yīng)用實(shí)例詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09

最新評(píng)論

遵化市| 印江| 邢台县| 岢岚县| 太保市| 珲春市| 郓城县| 南岸区| 新龙县| 高尔夫| 闻喜县| 静安区| 麻栗坡县| 江孜县| 哈巴河县| 内乡县| 阿鲁科尔沁旗| 托克逊县| 思南县| 通州区| 东兰县| 兴文县| 宁强县| 五指山市| 平湖市| 抚顺县| 缙云县| 巴彦淖尔市| 南投市| 高陵县| 安化县| 湖南省| 襄城县| 闸北区| 盱眙县| 那坡县| 满洲里市| 吴忠市| 丰城市| 习水县| 当阳市|