You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中DOM更新后如何重新运行ScriptTagger.js脚本?

BLB_ScriptTagger 动态内容处理解决方案

问题描述

我使用BlueLetterBible的BLB_ScriptTagger脚本时遇到了局限:按照官网「Website / Non-Wordpress Blog Installation」指引将脚本加入index.html和Helmet后,脚本仅能处理页面初始加载的元素——比如页面默认的「[Romans 1:16-18]」能正常生成提示,但后端API返回的动态内容里的经文(如「Romans 1:16-18」「Zephaniah 3:17」)无法被识别。用户会多次发起请求获取新内容,我需要每次API返回后让脚本重新处理这些动态内容。

之前尝试通过useEffect监听chatLog变化,移除并重新添加脚本,但未生效,代码如下:

useEffect(() => {
      const script = document.createElement('script');

      script.src = "https://www.blueletterbible.org/assets-v3/scripts/blbToolTip/BLB_ScriptTagger-min.js";
      script.async = true;
        console.log("reload")
      document.body.appendChild(script);

      return () => {
        document.body.removeChild(script);
      }
    }, [chatLog]); 

可行解决方案

核心思路

重复加载脚本会引发全局变量冲突,且异步加载的脚本无法保证和动态内容更新同步。正确的做法是只加载一次脚本,之后在动态内容更新时调用脚本暴露的全局扫描方法,重新处理新内容。

具体实现

import { useEffect, useRef } from 'react';

function YourComponent() {
  // 标记脚本是否已加载完成
  const isScriptLoaded = useRef(false);
  // 指向动态内容的容器,用于精准扫描
  const chatContainerRef = useRef(null);

  // 首次加载脚本,仅执行一次
  useEffect(() => {
    if (isScriptLoaded.current) return;

    const script = document.createElement('script');
    script.src = "https://www.blueletterbible.org/assets-v3/scripts/blbToolTip/BLB_ScriptTagger-min.js";
    script.async = true;
    
    script.onload = () => {
      isScriptLoaded.current = true;
      // 首次扫描页面初始内容
      window.BLBScriptTagger?.tag();
    };

    document.body.appendChild(script);

    return () => {
      document.body.removeChild(script);
      isScriptLoaded.current = false;
    };
  }, []);

  // 监听chatLog变化,重新扫描动态内容
  useEffect(() => {
    if (!isScriptLoaded.current) return;

    // 等待DOM完成更新后再扫描
    requestAnimationFrame(() => {
      // 优先扫描指定容器,提升性能
      const targetElement = chatContainerRef.current || document.body;
      if (window.BLBScriptTagger?.tag) {
        window.BLBScriptTagger.tag(targetElement);
      } else {
        // 兼容旧版本脚本,尝试重新初始化
        const initScript = document.createElement('script');
        initScript.textContent = 'BLBScriptTagger.init();';
        document.body.appendChild(initScript);
        document.body.removeChild(initScript);
      }
    });
  }, [chatLog]);

  return (
    <div ref={chatContainerRef}>
      {/* 渲染动态聊天内容 */}
      {chatLog.map((item) => (
        <div key={item.id}>{item.content}</div>
      ))}
    </div>
  );
}

关键细节

  1. 单次脚本加载:通过isScriptLoaded ref避免重复添加脚本,减少网络请求和全局变量冲突。
  2. 精准扫描范围:用chatContainerRef指向动态内容容器,仅扫描该区域而非整个页面,提升性能。
  3. DOM更新等待:使用requestAnimationFrame确保动态内容已经渲染到DOM中,避免脚本扫描时内容未更新。
  4. 版本兼容:如果tag()方法不存在,尝试调用init()方法重新初始化脚本逻辑,适配不同版本的BLB_ScriptTagger。

内容的提问来源于stack exchange,提问作者Nano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 16:40:21